{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "8976e7af-70fa-49d7-8196-9d24b1eb3734",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Looking in indexes: https://repo.huaweicloud.com/repository/pypi/simple/\n",
      "Requirement already satisfied: download in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (0.3.5)\n",
      "Requirement already satisfied: tqdm in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from download) (4.67.1)\n",
      "Requirement already satisfied: six in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from download) (1.16.0)\n",
      "Requirement already satisfied: requests in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from download) (2.32.3)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from requests->download) (3.4.1)\n",
      "Requirement already satisfied: idna<4,>=2.5 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from requests->download) (3.10)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from requests->download) (2.3.0)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /home/mindspore/miniconda/envs/jupyter/lib/python3.9/site-packages (from requests->download) (2025.1.31)\n",
      "\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m25.0.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m25.2\u001b[0m\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpython -m pip install --upgrade pip\u001b[0m\n",
      "Creating data folder...\n",
      "Downloading data from https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/datasets/cifar-10-binary.tar.gz (162.2 MB)\n",
      "\n",
      "file_sizes: 100%|█████████████████████████████| 170M/170M [00:00<00:00, 407MB/s]\n",
      "Extracting tar.gz file...\n",
      "Successfully downloaded / unzipped to ./datasets-cifar10-bin\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'./datasets-cifar10-bin'"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "!pip install download\n",
    "from download import download\n",
    "\n",
    "url = \"https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/datasets/cifar-10-binary.tar.gz\"\n",
    "\n",
    "download(url, \"./datasets-cifar10-bin\", kind=\"tar.gz\", replace=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "cdb86730-2c82-4104-ad00-9aea7946d2f5",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "import mindspore as ms\n",
    "import mindspore.dataset as ds\n",
    "import mindspore.dataset.vision as vision\n",
    "import mindspore.dataset.transforms as transforms\n",
    "from mindspore import dtype as mstype\n",
    "\n",
    "data_dir = \"./datasets-cifar10-bin/cifar-10-batches-bin\"  # 数据集根目录\n",
    "batch_size = 256  # 批量大小\n",
    "image_size = 32  # 训练图像空间大小\n",
    "workers = 4  # 并行线程个数\n",
    "num_classes = 10  # 分类数量\n",
    "\n",
    "\n",
    "def create_dataset_cifar10(dataset_dir, usage, resize, batch_size, workers):\n",
    "\n",
    "    data_set = ds.Cifar10Dataset(dataset_dir=dataset_dir,\n",
    "                                 usage=usage,\n",
    "                                 num_parallel_workers=workers,\n",
    "                                 shuffle=True)\n",
    "\n",
    "    trans = []\n",
    "    if usage == \"train\":\n",
    "        trans += [\n",
    "            vision.RandomCrop((32, 32), (4, 4, 4, 4)),\n",
    "            vision.RandomHorizontalFlip(prob=0.5)\n",
    "        ]\n",
    "\n",
    "    trans += [\n",
    "        vision.Resize(resize),\n",
    "        vision.Rescale(1.0 / 255.0, 0.0),\n",
    "        vision.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010]),\n",
    "        vision.HWC2CHW()\n",
    "    ]\n",
    "\n",
    "    target_trans = transforms.TypeCast(mstype.int32)\n",
    "\n",
    "    # 数据映射操作\n",
    "    data_set = data_set.map(operations=trans,\n",
    "                            input_columns='image',\n",
    "                            num_parallel_workers=workers)\n",
    "\n",
    "    data_set = data_set.map(operations=target_trans,\n",
    "                            input_columns='label',\n",
    "                            num_parallel_workers=workers)\n",
    "\n",
    "    # 批量操作\n",
    "    data_set = data_set.batch(batch_size)\n",
    "\n",
    "    return data_set\n",
    "\n",
    "\n",
    "# 获取处理后的训练与测试数据集\n",
    "\n",
    "dataset_train = create_dataset_cifar10(dataset_dir=data_dir,\n",
    "                                       usage=\"train\",\n",
    "                                       resize=image_size,\n",
    "                                       batch_size=batch_size,\n",
    "                                       workers=workers)\n",
    "step_size_train = dataset_train.get_dataset_size()\n",
    "\n",
    "dataset_val = create_dataset_cifar10(dataset_dir=data_dir,\n",
    "                                     usage=\"test\",\n",
    "                                     resize=image_size,\n",
    "                                     batch_size=batch_size,\n",
    "                                     workers=workers)\n",
    "step_size_val = dataset_val.get_dataset_size()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "c21f7da5-24dc-4426-be7c-bf3e771d7716",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Image shape: (256, 3, 32, 32), Label shape: (256,)\n",
      "Labels: [4 5 1 3 4 0]\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAgMAAAGFCAYAAABg2vAPAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8ekN5oAAAACXBIWXMAAA9hAAAPYQGoP6dpAABrkElEQVR4nO29ebRdVZnu/a61dt+cNic56U9y0kECghFQugACAUFu5AKity4xSoHip5e6UnXLqk8BO75RpTV04LChLANUcasJKFVaChYKgoJ0BgiE5oTkJCHNyemb3e+95vcHxRm+DeaYgnTr+Y3hGM7Ju+daa6651p5nv0+e13POOQIAAABAZPEP9QkAAAAA4NCCzQAAAAAQcbAZAAAAACIONgMAAABAxMFmAAAAAIg42AwAAAAAEQebAQAAACDiYDMAAAAARBxsBgAAAICIg83AfrjpppvI87xDfRoA/JfAOgbg99PV1UUXX3zxfuMeeugh8jyPHnroocm+j3zkI9TV1fX2ndxBAJsBAAAAbwvf+ta36Pbbbz/UpwGmQOxQnwAAAICjk29961s0bdo0+shHPnKoT+Ut48wzz6RSqUSJROJQn8pbCn4ZOAwpFAqH+hQAAAAY+L5PqVSKfP/o+vo8uq7mv8ivfvUrOumkkyiVSlF3dzd997vfNeP+4R/+gVauXEnpdJra2troyiuvpJ07d6q4xx9/nC644AJqbm6mTCZDq1atol//+tcs5o1c7ubNm+nDH/4wtba20umnn/62XB+IBlNZx/V6nb74xS9Sd3c3JZNJ6urqor/4i7+gSqXC4sIwpJtuuolmzZpFmUyGzj77bNq8eTN1dXUdVX/tAaLt27fTddddR0uXLqV0Ok3t7e10+eWXU29vL4t7M/3J7bffTp7nTcZ3dXXRCy+8QL/85S/J8zzyPI/OOuusyfitW7fS5ZdfTm1tbZTJZOjd7343/fu//zsb8438/L/8y7/QzTffTLNnz6Z8Pk+XXXYZjY6OUqVSoeuvv56mT59OuVyO1q1bp9bwVNf6G/zsZz+jE044gVKpFB177LH0gx/8wDyn39UMWIRhSF//+tdp+fLllEqlaMaMGXTttdfS8PDw7/3coQJpgv9k06ZNdP7551NHRwfddNNNVK/X6cYbb6QZM2awuC9/+cv0uc99jq644gq6+uqrqb+/n2699VY688wzaePGjdTS0kJERL/4xS/owgsvpJUrV9KNN95Ivu/T+vXr6ZxzzqFHHnmETj75ZDbu5ZdfTosXL6avfOUrhKrS4ECZ6jq++uqr6Y477qDLLruMPvOZz9Djjz9Ot9xyC7344ov0wx/+cDLus5/9LP3VX/0Vvf/976fVq1fTs88+S6tXr6ZyuXywLw28zTz55JP06KOP0pVXXklz5syh3t5e+va3v01nnXUWbd68mTKZzB803te//nX61Kc+Rblcjv7yL/+SiGhyHfb19dGpp55KxWKRPv3pT1N7ezvdcccddMkll9Ddd99NH/jAB9hYt9xyC6XTafrzP/9z2rJlC916660Uj8fJ930aHh6mm266iX7zm9/Q7bffTgsWLKDPf/7zk5+d6lonIurp6aEPfvCD9PGPf5zWrl1L69evp8svv5zuu+8+Ou+88/6g67/22mvp9ttvp3Xr1tGnP/1p2rZtG33zm9+kjRs30q9//WuKx+N/0HhvOw4455xbs2aNS6VSbvv27ZN9mzdvdkEQuDemqbe31wVB4L785S+zz27atMnFYrHJ/jAM3eLFi93q1atdGIaTccVi0S1YsMCdd955k3033nijIyL3oQ996O28PBARprKOn3nmGUdE7uqrr2afveGGGxwRuV/84hfOOef27t3rYrGYW7NmDYu76aabHBG5tWvXvr0XAw4qxWJR9T322GOOiNydd9452ffGO0uyfv16R0Ru27Ztk33Lly93q1atUrHXX3+9IyL3yCOPTPaNj4+7BQsWuK6uLtdoNJxzzj344IOOiNyKFStctVqdjP3Qhz7kPM9zF154IRv3Pe95j5s/f/5ke6pr3Tnn5s+f74jI3XPPPZN9o6OjbubMme7EE0+c7HvjnB588MHJvrVr17LjPvLII46I3F133cWOe99995n9hwNIExBRo9Gg+++/n9asWUPz5s2b7D/mmGNo9erVk+0f/OAHFIYhXXHFFTQwMDD5v87OTlq8eDE9+OCDRET0zDPPUE9PD334wx+mwcHBybhCoUDvfe976eGHH6YwDNk5fPzjHz84FwuOWqa6jn/yk58QEdH//t//m33+M5/5DBHR5E+1P//5z6ler9N1113H4j71qU+9LecPDi3pdHry/9dqNRocHKRFixZRS0sL/fa3v31Lj/WTn/yETj75ZJYSzeVydM0111Bvby9t3ryZ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ypWUTqepra2NrrzyStq5c6eKe/zxx+mCCy6g5uZmymQytGrVKvr1r3/NYt7QJGzevJk+/OEPU2trK51++ulvy/WBw5Pt27fTddddR0uXLqV0Ok3t7e10+eWXU29vL4uzcvtnnXUWrVixgp5++mk688wzKZPJ0F/8xV8QEVFXVxddfPHF9LOf/YxOOOEESqVSdOyxx9IPfvCD/Z7TI488QpdffjnNmzePkskkzZ07l/7kT/6ESqUSi/vIRz5CuVyOdu3aRWvWrKFcLkcdHR10ww03UKPRYLFhGNLXv/51Wr58OaVSKZoxYwZde+21NDw8fGATdxiCNMF+2L17N5188sk0MjJC11xzDS1btox27dpFd999NxWLRdq6dSvde++9dPnll9OCBQuor6+Pvvvd79KqVato8+bNNGvWLDrmmGPoC1/4An3+85+na665hs444wwiIjr11FMP8dWBo4FNmzbR+eefTx0dHXTTTTdRvV6nG2+8kWbMmMHivvzlL9PnPvc5uuKKK+jqq6+m/v5+uvXWW+nMM8+kjRs3UktLCxER/eIXv6ALL7yQVq5cSTfeeCP5vk/r16+nc845hx555BE6+eST2biXX345LV68mL7yla+Qc+5gXTY4DHjyySfp0UcfpSuvvJLmzJlDvb299O1vf5vOOuss2rx5M2Uymd/7+cHBQbrwwgvpyiuvpD/6oz9ia7anp4c++MEP0sc//nFau3YtrV+/ni6//HK677776LzzznvTMTds2EDFYpE+8YlPUHt7Oz3xxBN066230muvvUYbNmxgsY1Gg1avXk2nnHIKffWrX6UHHniAvva1r1F3dzd94hOfmIy79tpr6fbbb6d169bRpz/9adq2bRt985vfpI0bN9Kvf/1risfjBziDhxEO/F6uuuoq5/u+e/LJJ9V/C8PQlctl12g0WP+2bdtcMpl0X/jCFyb7nnzySUdEbv369W/3KYOIsWbNGpdKpdz27dsn+zZv3uyCIHBvPOK9vb0uCAL35S9/mX1206ZNLhaLTfaHYegWL17sVq9e7cIwnIwrFotuwYIF7rzzzpvsu/HGGx0RuQ996ENv5+WBw5hisaj6HnvsMUdE7s4775zse/DBBx0RuQcffHCyb9WqVY6I3He+8x01xvz58x0RuXvuuWeyb3R01M2cOdOdeOKJv3dc65xuueUW53kee0bW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",
      "text/plain": [
       "<Figure size 640x480 with 6 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "\n",
    "data_iter = next(dataset_train.create_dict_iterator())\n",
    "\n",
    "images = data_iter[\"image\"].asnumpy()\n",
    "labels = data_iter[\"label\"].asnumpy()\n",
    "print(f\"Image shape: {images.shape}, Label shape: {labels.shape}\")\n",
    "\n",
    "# 训练数据集中，前六张图片所对应的标签\n",
    "print(f\"Labels: {labels[:6]}\")\n",
    "\n",
    "classes = []\n",
    "\n",
    "with open(data_dir + \"/batches.meta.txt\", \"r\") as f:\n",
    "    for line in f:\n",
    "        line = line.rstrip()\n",
    "        if line:\n",
    "            classes.append(line)\n",
    "\n",
    "# 训练数据集的前六张图片\n",
    "plt.figure()\n",
    "for i in range(6):\n",
    "    plt.subplot(2, 3, i + 1)\n",
    "    image_trans = np.transpose(images[i], (1, 2, 0))\n",
    "    mean = np.array([0.4914, 0.4822, 0.4465])\n",
    "    std = np.array([0.2023, 0.1994, 0.2010])\n",
    "    image_trans = std * image_trans + mean\n",
    "    image_trans = np.clip(image_trans, 0, 1)\n",
    "    plt.title(f\"{classes[labels[i]]}\")\n",
    "    plt.imshow(image_trans)\n",
    "    plt.axis(\"off\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "7837b510-a606-4259-99b8-6dc774a34ab2",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "from typing import Type, Union, List, Optional\n",
    "import mindspore.nn as nn\n",
    "from mindspore.common.initializer import Normal\n",
    "\n",
    "# 初始化卷积层与BatchNorm的参数\n",
    "weight_init = Normal(mean=0, sigma=0.02)\n",
    "gamma_init = Normal(mean=1, sigma=0.02)\n",
    "\n",
    "class ResidualBlockBase(nn.Cell):\n",
    "    expansion: int = 1  # 最后一个卷积核数量与第一个卷积核数量相等\n",
    "\n",
    "    def __init__(self, in_channel: int, out_channel: int,\n",
    "                 stride: int = 1, norm: Optional[nn.Cell] = None,\n",
    "                 down_sample: Optional[nn.Cell] = None) -> None:\n",
    "        super(ResidualBlockBase, self).__init__()\n",
    "        if not norm:\n",
    "            self.norm = nn.BatchNorm2d(out_channel)\n",
    "        else:\n",
    "            self.norm = norm\n",
    "\n",
    "        self.conv1 = nn.Conv2d(in_channel, out_channel,\n",
    "                               kernel_size=3, stride=stride,\n",
    "                               weight_init=weight_init)\n",
    "        self.conv2 = nn.Conv2d(in_channel, out_channel,\n",
    "                               kernel_size=3, weight_init=weight_init)\n",
    "        self.relu = nn.ReLU()\n",
    "        self.down_sample = down_sample\n",
    "\n",
    "    def construct(self, x):\n",
    "        \"\"\"ResidualBlockBase construct.\"\"\"\n",
    "        identity = x  # shortcuts分支\n",
    "\n",
    "        out = self.conv1(x)  # 主分支第一层：3*3卷积层\n",
    "        out = self.norm(out)\n",
    "        out = self.relu(out)\n",
    "        out = self.conv2(out)  # 主分支第二层：3*3卷积层\n",
    "        out = self.norm(out)\n",
    "\n",
    "        if self.down_sample is not None:\n",
    "            identity = self.down_sample(x)\n",
    "        out += identity  # 输出为主分支与shortcuts之和\n",
    "        out = self.relu(out)\n",
    "\n",
    "        return out"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "2ea535fa-57ca-4ba0-9560-9f3360db2c45",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "class ResidualBlock(nn.Cell):\n",
    "    expansion = 4  # 最后一个卷积核的数量是第一个卷积核数量的4倍\n",
    "\n",
    "    def __init__(self, in_channel: int, out_channel: int,\n",
    "                 stride: int = 1, down_sample: Optional[nn.Cell] = None) -> None:\n",
    "        super(ResidualBlock, self).__init__()\n",
    "\n",
    "        self.conv1 = nn.Conv2d(in_channel, out_channel,\n",
    "                               kernel_size=1, weight_init=weight_init)\n",
    "        self.norm1 = nn.BatchNorm2d(out_channel)\n",
    "        self.conv2 = nn.Conv2d(out_channel, out_channel,\n",
    "                               kernel_size=3, stride=stride,\n",
    "                               weight_init=weight_init)\n",
    "        self.norm2 = nn.BatchNorm2d(out_channel)\n",
    "        self.conv3 = nn.Conv2d(out_channel, out_channel * self.expansion,\n",
    "                               kernel_size=1, weight_init=weight_init)\n",
    "        self.norm3 = nn.BatchNorm2d(out_channel * self.expansion)\n",
    "\n",
    "        self.relu = nn.ReLU()\n",
    "        self.down_sample = down_sample\n",
    "\n",
    "    def construct(self, x):\n",
    "\n",
    "        identity = x  # shortcuts分支\n",
    "\n",
    "        out = self.conv1(x)  # 主分支第一层：1*1卷积层\n",
    "        out = self.norm1(out)\n",
    "        out = self.relu(out)\n",
    "        out = self.conv2(out)  # 主分支第二层：3*3卷积层\n",
    "        out = self.norm2(out)\n",
    "        out = self.relu(out)\n",
    "        out = self.conv3(out)  # 主分支第三层：1*1卷积层\n",
    "        out = self.norm3(out)\n",
    "\n",
    "        if self.down_sample is not None:\n",
    "            identity = self.down_sample(x)\n",
    "\n",
    "        out += identity  # 输出为主分支与shortcuts之和\n",
    "        out = self.relu(out)\n",
    "\n",
    "        return out"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "f769e21b-4bfb-4ab2-95f7-8abb95a62ed0",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "def make_layer(last_out_channel, block: Type[Union[ResidualBlockBase, ResidualBlock]],\n",
    "               channel: int, block_nums: int, stride: int = 1):\n",
    "    down_sample = None  # shortcuts分支\n",
    "\n",
    "    if stride != 1 or last_out_channel != channel * block.expansion:\n",
    "\n",
    "        down_sample = nn.SequentialCell([\n",
    "            nn.Conv2d(last_out_channel, channel * block.expansion,\n",
    "                      kernel_size=1, stride=stride, weight_init=weight_init),\n",
    "            nn.BatchNorm2d(channel * block.expansion, gamma_init=gamma_init)\n",
    "        ])\n",
    "\n",
    "    layers = []\n",
    "    layers.append(block(last_out_channel, channel, stride=stride, down_sample=down_sample))\n",
    "\n",
    "    in_channel = channel * block.expansion\n",
    "    # 堆叠残差网络\n",
    "    for _ in range(1, block_nums):\n",
    "\n",
    "        layers.append(block(in_channel, channel))\n",
    "\n",
    "    return nn.SequentialCell(layers)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "62a47c64-eb8d-4f04-8f0b-3fe5d39034b0",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "from mindspore import load_checkpoint, load_param_into_net\n",
    "\n",
    "\n",
    "class ResNet(nn.Cell):\n",
    "    def __init__(self, block: Type[Union[ResidualBlockBase, ResidualBlock]],\n",
    "                 layer_nums: List[int], num_classes: int, input_channel: int) -> None:\n",
    "        super(ResNet, self).__init__()\n",
    "\n",
    "        self.relu = nn.ReLU()\n",
    "        # 第一个卷积层，输入channel为3（彩色图像），输出channel为64\n",
    "        self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, weight_init=weight_init)\n",
    "        self.norm = nn.BatchNorm2d(64)\n",
    "        # 最大池化层，缩小图片的尺寸\n",
    "        self.max_pool = nn.MaxPool2d(kernel_size=3, stride=2, pad_mode='same')\n",
    "        # 各个残差网络结构块定义\n",
    "        self.layer1 = make_layer(64, block, 64, layer_nums[0])\n",
    "        self.layer2 = make_layer(64 * block.expansion, block, 128, layer_nums[1], stride=2)\n",
    "        self.layer3 = make_layer(128 * block.expansion, block, 256, layer_nums[2], stride=2)\n",
    "        self.layer4 = make_layer(256 * block.expansion, block, 512, layer_nums[3], stride=2)\n",
    "        # 平均池化层\n",
    "        self.avg_pool = nn.AvgPool2d()\n",
    "        # flattern层\n",
    "        self.flatten = nn.Flatten()\n",
    "        # 全连接层\n",
    "        self.fc = nn.Dense(in_channels=input_channel, out_channels=num_classes)\n",
    "\n",
    "    def construct(self, x):\n",
    "\n",
    "        x = self.conv1(x)\n",
    "        x = self.norm(x)\n",
    "        x = self.relu(x)\n",
    "        x = self.max_pool(x)\n",
    "\n",
    "        x = self.layer1(x)\n",
    "        x = self.layer2(x)\n",
    "        x = self.layer3(x)\n",
    "        x = self.layer4(x)\n",
    "\n",
    "        x = self.avg_pool(x)\n",
    "        x = self.flatten(x)\n",
    "        x = self.fc(x)\n",
    "\n",
    "        return x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "013c992b-7284-483f-a6c4-c5f522d4a786",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "def _resnet(model_url: str, block: Type[Union[ResidualBlockBase, ResidualBlock]],\n",
    "            layers: List[int], num_classes: int, pretrained: bool, pretrained_ckpt: str,\n",
    "            input_channel: int):\n",
    "    model = ResNet(block, layers, num_classes, input_channel)\n",
    "\n",
    "    if pretrained:\n",
    "        # 加载预训练模型\n",
    "        download(url=model_url, path=pretrained_ckpt, replace=True)\n",
    "        param_dict = load_checkpoint(pretrained_ckpt)\n",
    "        load_param_into_net(model, param_dict)\n",
    "\n",
    "    return model\n",
    "\n",
    "\n",
    "def resnet50(num_classes: int = 1000, pretrained: bool = False):\n",
    "    \"\"\"ResNet50模型\"\"\"\n",
    "    resnet50_url = \"https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/models/application/resnet50_224_new.ckpt\"\n",
    "    resnet50_ckpt = \"./LoadPretrainedModel/resnet50_224_new.ckpt\"\n",
    "    return _resnet(resnet50_url, ResidualBlock, [3, 4, 6, 3], num_classes,\n",
    "                   pretrained, resnet50_ckpt, 2048)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "58d2a281-8eda-4d2b-9647-f8bba0473e1b",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading data from https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/models/application/resnet50_224_new.ckpt (97.7 MB)\n",
      "\n",
      "file_sizes: 100%|█████████████████████████████| 102M/102M [00:00<00:00, 355MB/s]\n",
      "Successfully downloaded file to ./LoadPretrainedModel/resnet50_224_new.ckpt\n"
     ]
    }
   ],
   "source": [
    "import mindspore\n",
    "# 定义ResNet50网络\n",
    "network = resnet50(pretrained=True)\n",
    "\n",
    "# 全连接层输入层的大小\n",
    "in_channel = network.fc.in_channels\n",
    "fc = nn.Dense(in_channels=in_channel, out_channels=10)\n",
    "# 重置全连接层\n",
    "network.fc = fc"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "ce917b99-2ca4-4dd8-866c-818bd2110e43",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# 设置学习率\n",
    "num_epochs = 5\n",
    "lr = nn.cosine_decay_lr(min_lr=0.00001, max_lr=0.001, total_step=step_size_train * num_epochs,\n",
    "                        step_per_epoch=step_size_train, decay_epoch=num_epochs)\n",
    "# 定义优化器和损失函数\n",
    "opt = nn.Momentum(params=network.trainable_params(), learning_rate=lr, momentum=0.9)\n",
    "loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')\n",
    "\n",
    "\n",
    "def forward_fn(inputs, targets):\n",
    "    logits = network(inputs)\n",
    "    loss = loss_fn(logits, targets)\n",
    "    return loss\n",
    "\n",
    "\n",
    "grad_fn = ms.value_and_grad(forward_fn, None, opt.parameters)\n",
    "\n",
    "\n",
    "def train_step(inputs, targets):\n",
    "    loss, grads = grad_fn(inputs, targets)\n",
    "    opt(grads)\n",
    "    return loss"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "a00f541d-11f7-4b82-88af-9e869e2e8d47",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "# 创建迭代器\n",
    "data_loader_train = dataset_train.create_tuple_iterator(num_epochs=num_epochs)\n",
    "data_loader_val = dataset_val.create_tuple_iterator(num_epochs=num_epochs)\n",
    "\n",
    "# 最佳模型存储路径\n",
    "best_acc = 0\n",
    "best_ckpt_dir = \"./BestCheckpoint\"\n",
    "best_ckpt_path = \"./BestCheckpoint/resnet50-best.ckpt\"\n",
    "\n",
    "if not os.path.exists(best_ckpt_dir):\n",
    "    os.mkdir(best_ckpt_dir)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "16cdfe54-dc73-4c7d-a88d-e4fd75469417",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "import mindspore.ops as ops\n",
    "\n",
    "\n",
    "def train(data_loader, epoch):\n",
    "    \"\"\"模型训练\"\"\"\n",
    "    losses = []\n",
    "    network.set_train(True)\n",
    "\n",
    "    for i, (images, labels) in enumerate(data_loader):\n",
    "        loss = train_step(images, labels)\n",
    "        if i % 100 == 0 or i == step_size_train - 1:\n",
    "            print('Epoch: [%3d/%3d], Steps: [%3d/%3d], Train Loss: [%5.3f]' %\n",
    "                  (epoch + 1, num_epochs, i + 1, step_size_train, loss))\n",
    "        losses.append(loss)\n",
    "\n",
    "    return sum(losses) / len(losses)\n",
    "\n",
    "\n",
    "def evaluate(data_loader):\n",
    "    \"\"\"模型验证\"\"\"\n",
    "    network.set_train(False)\n",
    "\n",
    "    correct_num = 0.0  # 预测正确个数\n",
    "    total_num = 0.0  # 预测总数\n",
    "\n",
    "    for images, labels in data_loader:\n",
    "        logits = network(images)\n",
    "        pred = logits.argmax(axis=1)  # 预测结果\n",
    "        correct = ops.equal(pred, labels).reshape((-1, ))\n",
    "        correct_num += correct.sum().asnumpy()\n",
    "        total_num += correct.shape[0]\n",
    "\n",
    "    acc = correct_num / total_num  # 准确率\n",
    "\n",
    "    return acc"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "085562b9-01d7-4162-af17-23d1d0e3cda9",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Start Training Loop ...\n",
      "Epoch: [  1/  5], Steps: [  1/196], Train Loss: [2.304]\n",
      "Epoch: [  1/  5], Steps: [101/196], Train Loss: [1.428]\n",
      "Epoch: [  1/  5], Steps: [196/196], Train Loss: [1.112]\n",
      "--------------------------------------------------\n",
      "Epoch: [  1/  5], Average Train Loss: [1.618], Accuracy: [0.586]\n",
      "--------------------------------------------------\n",
      "Epoch: [  2/  5], Steps: [  1/196], Train Loss: [1.078]\n",
      "Epoch: [  2/  5], Steps: [101/196], Train Loss: [0.927]\n",
      "Epoch: [  2/  5], Steps: [196/196], Train Loss: [0.795]\n",
      "--------------------------------------------------\n",
      "Epoch: [  2/  5], Average Train Loss: [1.012], Accuracy: [0.678]\n",
      "--------------------------------------------------\n",
      "Epoch: [  3/  5], Steps: [  1/196], Train Loss: [0.875]\n",
      "Epoch: [  3/  5], Steps: [101/196], Train Loss: [0.826]\n",
      "Epoch: [  3/  5], Steps: [196/196], Train Loss: [0.648]\n",
      "--------------------------------------------------\n",
      "Epoch: [  3/  5], Average Train Loss: [0.851], Accuracy: [0.721]\n",
      "--------------------------------------------------\n",
      "Epoch: [  4/  5], Steps: [  1/196], Train Loss: [0.784]\n",
      "Epoch: [  4/  5], Steps: [101/196], Train Loss: [0.814]\n",
      "Epoch: [  4/  5], Steps: [196/196], Train Loss: [0.879]\n",
      "--------------------------------------------------\n",
      "Epoch: [  4/  5], Average Train Loss: [0.778], Accuracy: [0.732]\n",
      "--------------------------------------------------\n",
      "Epoch: [  5/  5], Steps: [  1/196], Train Loss: [0.851]\n",
      "Epoch: [  5/  5], Steps: [101/196], Train Loss: [0.821]\n",
      "Epoch: [  5/  5], Steps: [196/196], Train Loss: [0.566]\n",
      "--------------------------------------------------\n",
      "Epoch: [  5/  5], Average Train Loss: [0.745], Accuracy: [0.737]\n",
      "--------------------------------------------------\n",
      "================================================================================\n",
      "End of validation the best Accuracy is:  0.737, save the best ckpt file in ./BestCheckpoint/resnet50-best.ckpt\n"
     ]
    }
   ],
   "source": [
    "# 开始循环训练\n",
    "print(\"Start Training Loop ...\")\n",
    "\n",
    "for epoch in range(num_epochs):\n",
    "    curr_loss = train(data_loader_train, epoch)\n",
    "    curr_acc = evaluate(data_loader_val)\n",
    "\n",
    "    print(\"-\" * 50)\n",
    "    print(\"Epoch: [%3d/%3d], Average Train Loss: [%5.3f], Accuracy: [%5.3f]\" % (\n",
    "        epoch+1, num_epochs, curr_loss, curr_acc\n",
    "    ))\n",
    "    print(\"-\" * 50)\n",
    "\n",
    "    # 保存当前预测准确率最高的模型\n",
    "    if curr_acc > best_acc:\n",
    "        best_acc = curr_acc\n",
    "        ms.save_checkpoint(network, best_ckpt_path)\n",
    "\n",
    "print(\"=\" * 80)\n",
    "print(f\"End of validation the best Accuracy is: {best_acc: 5.3f}, \"\n",
    "      f\"save the best ckpt file in {best_ckpt_path}\", flush=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "ce898e91-26b6-494f-aad0-8d3dcb9f9b12",
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAgMAAAGFCAYAAABg2vAPAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8ekN5oAAAACXBIWXMAAA9hAAAPYQGoP6dpAAB09klEQVR4nO29eZQtV3Xfv6vuPPW9Pb7uN0+aJcAIAwYbMZrJEAxYEE9gC3BiMNgrJomTXwzE8RRiGxsntnFizOQBUMzCsQ0xBptRYCQhJD096c1zz31v375zVZ3fH5W3Wvt8j/SumvfULer7WUvr6Zzet4ZTp6pP1/7e7/aMMUYIIYQQklj8zT4AQgghhGwuXAwQQgghCYeLAUIIISThcDFACCGEJBwuBgghhJCEw8UAIYQQknC4GCCEEEISDhcDhBBCSMLhYoAQQghJOFwMWPzjP4p4XvzvRd74RpG9ex+f/X/kIyLXXiuSyYjUao/PPsl3B5y75InGZs9ZF899bvxf0uBi4Arya78m8qlPDR9/+HB8Ixw4IPLHfyzygQ9cqSMj5NHh3CVPNB7rnCWa9GYfwBOBP/5jkSh67J/7tV8Tee1rRV71quHi//Ef4/387u+KHDz42PdHiA3nLnmi8XjNWaL5rnkzEEUi3e6V2XYmI5LLXZltP5z5+fjfS71iNUak07nih0MeJzh3yRON74Y5u9Votzd3/1tuMfDud8c5pMOHRW69VWRkRGR8XOQd79CTz/NE3vY2kY99TOSGG+LJ85nPxD87d07kp39aZNu2uP+GG0T+5E9wX2fPxqvIUklkakrkF35BpNfDOFcO6+JfQTfdJJLPi0xOirzkJSLf/Ob68bVaIh/6UPz/nhdv5yKHD4ucPr3e3rtX5F3viv9/cjKOf/e713/2Qz8k8tnPijztaSKFgsgf/VH8s+PHRX7kR0TGxkSKRZFnPlPkb/4Gz+HUKZFXvlKf62c/i/k6snE4dzl3n2gkdc5e5AMfiFNbhYLI058u8qUvucep14vn+MGD8Tnu2iXyb/+t+/g/+lGRm2+Otzk2JvL614ucOaNjnvtckRtvFLnzTpHnPCee///hP7j3/XixZdMEt94aT4hf/3WRO+4Q+b3fE1lZEfnwh9djPv95kY9/PJ6kExNx/Nxc/FC5OHknJ0X+7u9EbrtNZHVV5Od/Pv5spyPyghfEE+TtbxfZvj0WQH3+88Md3223ifzpn4q89KUib3qTSBDEE+mOO+KH3kc+Evc//ekib3lL/JkDB9Y/f911Irfcsv4we9/74nP7q78S+YM/ECmXRZ70pPX4Bx8U+Zf/UuRnfkbkzW8Wueaa+Fyf9ax4Rfn2t8c38Yc+FD84P/lJkR/+4fizrZbI858vcuFCfJNPT4v82Z+JfOELj/WqkGHg3OXcfaKRtDkrIvK//lc8J5/1rPg4jx+P59/YWPzL/iJRFPd/+cvxtq+7TuTee0V+53dEHnpI6xR+9VdF/tN/isfzTW8SWVgQef/741/4d9+t35wtLcXn8/rXi/z4j8eLqU3FbDHe9S5jRIx55St1/8/+bNx/zz1xW8QY3zfm/vt13G23GTMzY8ziou5//euNqVaNabfj9vveF2/j4x9fj2m1jDl4MO7/whfW+9/wBmP27Flvf/7zcczb347HH0Xr/18qxZ91IWLMLbfovovnvrCg+/fsifs/8xnd//M/H/d/6Uvrfc2mMfv2GbN3rzFhGPf91m/FcZ/61Hpcp2PMtdfiuZKNw7nLuftEI6lztt83ZmrKmKc8xZheb73/Ax/A2I98JD73h89VY4z5wz+MY7/ylbh98qQxqZQxv/qrOu7ee41Jp3X/LbfEn/3DP3Qf72aw5dIEF3nrW3X7534u/vdv/3a975ZbRK6/fr1tjMjtt4u84hXx/y8urv/34heLNBoid921vp2ZmVhwcpFicX1V+Wjcfnu8Er74avTheN5w52fMY3vFuW9ffA4P52//Nl4Jf//3r/eVy/E5nDwpcuhQ3PeZz4js2BGvbi+Sz8d/pZHLD+euhnN365O0OfvNb8Y6l3/1r0Sy2fX+N75RpFrVn/3EJ+K3Addeq8/x+c+Pf37xLdX//t/xW4Rbb9Vx09MiV12Fb7NyOZGf+qnhjv/xYMumCa66SrcPHBDx/fhBcZF9+3TMwoJIvR7ngR7pq00XhU6nTsX5H3syXXPNpY/t2LH4NdfY2KVjLxf2uYrE5/CMZ2D/ddet//zGG+N/DxzAc6Xq+8rAuavh3N36JG3OnjoV/2ufdyYjsn+/7jtyROSBB+IUiIuL53jkSLzosLf58G0/nB079EJks9myiwEb1wqwUNDti19H+fEfF3nDG9zbeXgu84mEfa7kiQPn7mYfAXmsJH3OPpwoioWLv/3b7p9f1BdEUTxuf/d3IqkUxpXLur3V7ostuxg4ckSvRI8ejQf70ZypJidFKhWRMBR54Qsffft79ojcd1+8knv4xH/wwUsf24EDsZp5efnRV6vDvsLaKHv2uI/38OH1n1/899AhPNejR6/s8SUVzt1Lw7m7tUjanL04v44cWX/dLyIyGIicOCHy5Cfr/d9zTyyAfLR9HDgQn9++fSJXXz38sWwVtqxm4L//d91+//vjf1/60kf+TCol8prXxDmm++7Dny8srP//y14mcv58rFy+SLs9nHPaa14TX/T3vAd/Zsz6/5dK8Ws0F4/0VZfHwsteJvKNb4h87Wvrfa1WfA57967n91784vjrP5/+9Hpctxube5DLD+fupeHc3Vokbc4+7WnxYuYP/1Ck31/v/9M/xW3cems8B11zrtOJ562IyKtfHY/Je96jj+vicS4tPcIJbhG27JuBEydi0dBLXhI/MD76UZEf/VG9YnPxG78RCzWe8YxYZHT99fGK8q67RD73ufj/ReKf/f7vi/zkT8bf9ZyZib+eUixe+tie9zyRn/iJ+Os3R47ExxhF8Vddnve8+Cs2IvF3TT/3ufj10vbt8YrxYp7U9VWXx8q///cif/7n8Q379rfHq+YPfSgeu9tvj3N+IvHXZ37/9+Ovd73jHfG5fuxjsRBL5Mr/FZg0OHcvDefu1iJpczaTEfkv/yWeX89/vsjrXhePwQc/iJqBn/iJ+CuV/+pfxef67GfHb0MOH477L3poHDgQb/OXfinWWrzqVfGbkxMn4q/dvuUtIr/4i0NekM1gs7/OYHPxqy6HDhnz2tcaU6kYMzpqzNveFn+l6CIixrz1re5tzM3FP9u1y5hMxpjpaWNe8IL4ayMP59Sp+Cs1xaIxExPGvOMd8VegLvVVF2OMCQJj3vve+CtO2awxk5PGvPSlxtx553rM4cPGPOc5xhQK8TYf/rWXx/r1rJe/3H2ux47F41SrGZPPG/P0pxvzf/4Pxh0/Hm+jUIiP9d/8G2Nuvz3e3x13uLdNHhucu5y7TzSSPGeNMeZ//I/466y5nDFPe5oxX/xiHGfH9vvG/OZvGnPDDXHs6KgxN99szHveY0yjoWNvv92Y7//++KuOpVJ8zG99qzEPPrgec8st8ba2Ep4x9guNzeXd745fsywsxMYW5MrxvvfFLmBnz8bKVvKdwbn7+MG5e3ngnCUX2bKaAXJ5sf3gu93YFvaqq/gwJVsbzl1CrjxbVjNALi+vfrXI7t0iT3lKbAby0Y/GOa+PfWyzj4yQR4dzl5ArDxcDCeHFLxb5n/8zfoCGYSz0+Yu/iIUzhGxlOHcJufJsOc0AIYQQQh5fqBkghBBCEg4XA4QQQkjC4WKAEEIISThDCwh/9/xvQp8X6pJL7VYTYvJ5XbFhooylnwbnBqp99EuHcTthXrXLEzWI8cs56DMFve2Bj8dYX9F92RC3XSvoL+FW92Iliu74CvSdO9tQ7cYDaxCT7+tyVvsulm57+P626/2nc7j/c6ePqfbisQsQs/Kg4xhP23E4LQ7s1aW4OkEfYnLb9DXKl9Ae7jfe/FvQd6X5xbe8CfqWm6uq3YsCiKkWtD1aLo0lxurNlmo/dPQExOzdt0e1d07V8CCjDnS1G7pvbGQUYsZqen43mm2IWWnqa7W61oOYlIfzKV8bUe0wxM9lVxdU2/fw74vCtC531zZ4n0aWdKnfw/GIghD6JqxrZKIBxHh5q1xcEOExDvS4DQZdiHn3hz8FfVea//Le10NfOaXHL5dFGz+T1tdz0ZrvIiJzi/rajY+NQMz2Gf3cMYLjO+jjvCjmdRGBKMRnwSDQ23LNncjoa9Xt4XUJHLK3tHWvFvJliMlmdaWg1UYLYu6881uqvX//XojZvkP/TvN8fDZ6Hs65INTPHJd6r2+Nbb+P27b7BgE+y37lnR/HjVvwzQAhhBCScLgYIIQQQhIOFwOEEEJIwhlaM9CJlqHPi6w8iGNrQajzWStLuJ2J3LhqX3XtAdy/lT+NHPvKlTAXObp9u2qfXcWc7mRN55MGHVwjzUzOqHZ+FHM398yi1uHCuUXVvmnfkyCmNNC5q/vvxu0E9+iEUs2V35vS+b2JApqNn147B33ZnN5/u4352rmledU2jmVktapz2tt2bMOgzSCNueaZ7XrOpdI4oebPai1Ff4C5OF/0PTBarUBMIaPzpRlMz8vKGs6nvKURmNy7B2LKWa1BWV07BjH+QGti/BbWUvUc+drlxhnVzjrGqFzQ59Zcw7xrekTP1WJtBmIW23psS0Ucx95KHfpKI/reLVYKEGPS+tz6a5h3nj2qr3VtBHPMm8Go43wyvn6m1ldx7jx08qRqr7UxxpIVSKGAeqblVX3vjI9PQ0w+jc8iE+l5kc7g/Mrk9PO6a/tOi0gqpfUe1UIJYlpt1CxkLM2ArQ8QEUlb287n8Tlx4OBO1R6p4u+Ybk/rwrI51Ed4PgoCwlA/O4zBz4VhaMWg9gD2dckIN3wzQAghhCQcLgYIIYSQhMPFACGEEJJwhtYMDAb4PdWwq3NvYRvXFjlrvZEOMb/kWd+T9X3czrbtOleVH8HvfEeO74rbOcSGwf2vWDmfbgpzUC2jc6Fpg/tPRZiX2jGp9Q8L59Hn4PDxh1T73Il5iLG/b1vMYe5qtqLznNu3bYeYEIdICmX9ucpIFWJ61ndZXTn2tVWdc+wP8Hvxm8HYxDj0ZTM6X7iyjP4L27dpzcOZU2cgptvTA3rA8T3kA3t13tGPcH4tLixA3/ml46od9DHXP16x8uFtvE+bS1on4g3wu+LFIs6noKuPM+PhnDfW98ezGCKNeX0eXhN1Q72MpRHI1CAm72eg7+yszvVPGrzWIjo5vtLCm2Cxr8+j08Qx2gxyWTznfqCP9Z7DqBM5/NBp1S7m8J7euU3fnyePnYYYP631HcUi6pBy2Tz0pUTnulfXUI+QtSZLJotzMGPdp+k0PmP7fYcIx8qcD/qoBwitXzNVh94niPS4zc2dhRj7987oGI61UzOR1uPW613aQ8BFzvpdsNFyQ3wzQAghhCQcLgYIIYSQhMPFACGEEJJwuBgghBBCEs7QAsKwhQVQUn0tAJkp74UYr6tFGZP5/RAzWdBCt/N1NMbpd7WgZ2EFxVQSNqBr94Ep1U7bRkki4luCi0EPjVMuzOpjKpfwPGpFNOQ4c0ELBg/dfwRiSpbeo1RCY42gpcWaRQ9FO/UL+vxDPA1JZ/BzIyP6Go1UUEjTWK2rdiqDU8cvONRjW4Cjx1H0s31SiwPriyhwsg1fxkZRfLqjpPuyDrOciiXQzDiuXa2IwqiF0w+otl/BY8yVtWAuEhQnplO2cQkKjHwfBXNZTwuj0oJCrWxBn5vvoVArY4ugDN67g6bua0ZjENNz3F++ZfDSdZgeSVefh+ehLcu2cX3PZYKtISAMHBYypy9ogfH8Uh1iOh19HaImxmQmtBjQT+HcnRrZrTsGKGhsdlG0OlLV4xk65txyQz+vigW8B6pVLcYL+3hdHI90yeb088lEOC8jo+dlOoP7T6X1ca85ivF1u9osKZvDMSqWcNtRqPfv+3h/pVK6zzYhcmF/Zlj4ZoAQQghJOFwMEEIIIQmHiwFCCCEk4QytGfDqmKuppQ+q9s7qjfi5tM6fVAzmAr2mZQoyh3mZE6e1MY+XxdzoVfsw57W2dF61LyxdgBhTsApWCCahor4+prUVNInp9vG425bWYufBvRAzZuXKojrqM+aOacObahYLqeStnJcr65nPY+4qX9CmT5LCPGXVMtIoOnQNA+tjxmGusxn4jvxvf01fq+kaGiQ1V3UeuzPA86mNTar2oItzwAy0RiDvKD5TyWFOdfeU/lxJUDNgTzkvwvV9yte3eaPnKOySxc/Zed7WGhaS8fL63u0NMGc/UdHnUXZoS/I5vf+FNTzGQhVzsemCvue7Tdx/1tIsVEp4rtmsvucL+aEfjVeUC4uogzo1qzUD2VwRYgopPQ77tk1CzHOf9r2q7TnMg5qWfqrbQ31AuoR57GZT952/MAcxInp+eRM45imraFomhccYhnh/p9P2XMFnWtcy1Vpdc2hZBnZe33GfBPo8+g6DI4d3lES+jkun8RhBMxCgYRYWM6LpECGEEEI2ABcDhBBCSMLhYoAQQghJOFwMEEIIIQlnaJVMro0KiImKNt5ZPITChaClK5QdWXwIYhoNrYI6v4xikzCtTXeuu2kvxJRyKPxbPq+Fd+1VFHjtPniV3k4RBTnLdV3VbnX5BMR4eVxbzcxowWSlipUExRI41U+gkCU6occ28hwikbTef6GAIr9ytQZ9QaD3f2F2FmKKJS36Ko3gtvNW9cl0aWuIsK7dVYO+XkuLh1bm8Jw7Az2f2g5x3uKyvlapQR1iTtR11T7juHamj8K30aoWS0UDFA/1rWpwxkdxojFahNTuoMDJoSuVKKXv+e4Aha1LK3XVHqugOLBkGSpl8lidztT19Sj6KFaUtVPQVal9j952ZTfEtC1Do8jH8e9aled6DqHWZjBfR9HowrIWFTYcguuCde1e9APfBzE3Htin2vfcdx5ivvKlu1X7+1/kEIn7KCq8UNfH1HVU5LOFbsUiPlNsLZwRnLuej309S/joihHLVKvbxfkdWPOgXMaKhHb1QU/wd2UQoDjQ9/XzpeMQH9tjEkY4dz2roq1d4XZY+GaAEEIISThcDBBCCCEJh4sBQgghJOEMndRtXsAc2pkFXQAm1UNDof6qzsPMnsO833JLG/gUJzDvuGOPNs2Y2YMmGiPZLvQV8ztUu1LFfEo5X1PtfgdzNyNWyifyMO9ZdxilFK2wJUvDICJSt3KAcw+ioVHjrNYsRJhek6JVbKVQxWPMZLGIRd0qGJLO4Rqx39fnNmjjuY6VrcInjmJGm0EnwPPJlbRZTbaDOc1cWs/D8TxqSeZm9T3gdVHvkY70PZDJY04xk8KcZrmq91epTUFMq6lz6/VVzHvaPim1ETTnGhnBuRJYZiomwrxnsaKv8dgImsJk87ovk8E5GFlVtdIO4690Gseo29SapNwU5nRTBb3/haVliClaoolVR65+M+i30VBn0NZjE3ZxrHZs14W4ei3UpJw7eVK1yw4tx8yENjfrruH8WriAeptuRs/xbBrvnW7byuuHmA+3NiMmRC1Jy5Frzxt97/qC27ZNftKOQkFdS7RQLuF5ZO2DdBgcVSpoEmdE/05tO2QyvZ5tKOS4d6yCS8ajZoAQQgghG4CLAUIIISThcDFACCGEJBwuBgghhJCEM7TCKy9olpO1TGWqUyge+tYdD6p200ODisykFlxM7EN13LZdWhg0NT0OMcUIRWDtuj7Gkl2hT0RC63ODYBFiymkt3Dh3BmOW11CkkxnRApAVR+U3P6XFLqaDQshyRgtQimkUSpXLetwyRcflDRymHZYJztTEBMSMW1X9oh4KctorWnTlRxsTslxu6jicUi7o61nZhvO7VNZCuwvnUPyZssWBPgptc1k9vwtFFAH1+47Kin194E3Bbbe7OqY3wJOtVPR5VKt4f41OoKhwYUGLVjOZEYhJWaK+7gDvQa+j50Gmj/Mik9J9vsNcplJGYfGFFW1QttLE/RdGtbA5DYIvkVJF30+VEXy+bAae8+81fV8XiihOOz+rx+WODj6bRp6ljYgmZ/bg/i1h67e/fT/EtByVKjPj+pjGplBcXsjr65lyCN+yVgXVZguFy76g8LHXsSsCukSrVjtyVD+0RNDlGo51v49zziYM8d71rcqKBce17hh9kK0WCjgHgb7n80W8T4aBbwYIIYSQhMPFACGEEJJwuBgghBBCEs7QmoG1Ncyz5cs6D3PNjdfg5yxTkHsPo6GOV9R5kWwR89HlnM4dLZ45CjHdFTQKWVnUGoUowvMYHdU51HwZ867hQG9nsor6iKIjV3PWMji5ZhcWUsmXdS62arvEiMhcpPdfyWJlmbU1fdy1yijEDLqYFxsf0RqBfApzcDmrGIdxLCPPntV5ykrZUf1mEwgdhUPml3U+/HuedD3EjE9Oq/bhB74NMeWMlec0mD8s5/VtlvYcRVt8vC7tjs4P5ouo5SiUtQZmfhG1LL2enhdTE5i/zWQwF5qxtA6dDuYrbROrchXnXLWi76/mMprUpH09JjlHjjfsod6olKmptqOWlHgpva1BcwViFiztxfjkDojZDFo9fBZFVm7dyzkM0Br6WlUd2wmsp3+2jFoSP6vv+7UWztNmF/P4raZdQAuv564d2jjO89Csp24VPBIPn7G+wwCub2ln1hx6LvH0751UCvdfq+kxSafxV6ZvPa97PRwPu+CSiEhkFR0KQ9RMNBp6zrfbeA+WQEuD5zEMfDNACCGEJBwuBgghhJCEw8UAIYQQknC4GCCEEEISztACwoFD3GBXSJudQ/HSzt3ayOLM8kmI6URabNJqokgi6ugYr4+CmMZCHfru/fZpa9so3jpwlRYLPe2ZByBmYkpXjOu3sVJWYeCqVqWrhwU+juOFWS2GPHAAxUvBkjYrWp7FymtRWgv2VhbxGJsrDehrLOptVUfRXGbHHn0e27ZjBb2pHdqopZ3ZGpXfFubmsNPo8VxtYLXB+ZW6/kiExiG2ZtQ4fJY863MOzxsJfEfFNqtKYuRQIe09qOdqsYSizXMnjqt2t4NCvEYDt92yxEq2AYuIyA03XqvarqqJ58/qyo67Z2oQ00tZc8UxkG2HuYstKixP4L0zsMSIpof3RTqjxy3sOgRnm8AgQJOyfqT7UikUf+Ytw6zAIcica+qxKzRwXqSLejvdAc6THmoKpWE9nrMXcDx3bNup2guzjoqI81rsOTqK5lgTUw5RYU6fb9MhvOsFlmGYo6JrcaBv1tVVHKOUJVDtdh2iT4cBm7EqKa45qt42rd+FA8c9YFdfbHc29tzlmwFCCCEk4XAxQAghhCQcLgYIIYSQhMPFACGEEJJwhhYQ5vIoXFhenlftz37m/0JMKat3cc1NByGmPKrFOwsXTkNMKafXLfkUCjmmptBBq9fTYpuzZ85BzIT1uaNH0N3w6ECL0KZquK+Sw31tratdrhZWULy09xotAutHKADpDLQ4cxCh2GVyTAv4TBpdEreNT0LfUllve3b2PMQcO61FaHPdCxATWGXAqrtwjDaDbhfFQ1bBNGk5rkvLcggzjqpqYlV8TDmW133L/S2XQgVhrYwuaq1UTbW/fRKd8/bepOfczCSquVpz+lp1B1gRsNtB8VLKEliNjWMlv9KorvZ3ZB5C5KFz+tkxOopC24IlVLtwHkWfKR8/Vyxp8dxAHAK3UPelyzWIsYtNOna1KezZifdrz6qAtziH8zubt4R2aZxzdaua5Ge/+BWIOX9OX9DQ4Pxac9xfvZ4ewPGxbRAjRh/TkYfw2Zz2LXFkiOK8yQmcz9m8vhHt6osiIqmUnhf9AM+ja/3+CAIUEYehVbnTISC0RYYiIh3LudFEDndDT38uDHF+Lyxo8XPk4b08DHwzQAghhCQcLgYIIYSQhMPFACGEEJJwhtYMrCxgPicQbYqS8jCfMTGmc4rX7ccYk7Jyijk0tCmkdH5r9hTqCsrVGvTdfPN1qr1ax7yrGJ3z6TmqcM2e0ftbKeDQTVhV7kRE7CKBuQIa+hRSOrefL2B+78ABbdBxykOTnMWlY6o9tX0fxGRKaNqxbbs+7koNTUx6Ra1jKO1Eow9JW3m5EubpNoMnPeXJ0OeLPrado1jJL7SqmN29gvdAuWKZsgiaxHTaus84zEXSdvVDEVmxjLXuuPcsxFz/ZG0i9b278DzyOX2tAsefAKGP13NyVN/f22fQ0CeV17ngb953BGIay/omaKxh3jld1bqhTKnmOEjsGqnp8+2lihBjfK3HyDnui8mCnvOLiw7xwyawewZ1SCM1Pefuuw+fhRdO6fx3YxVz3d86dEq1O23UhWWz+lk06DvMmBwVN/ce0PPiqmtRb9Lvat1XvY5jnrYuereJkzft4cQY3aafs/kijmMY6v2nPHzu+in9nHfpAexKgtks3kvNpsvoSz9Tczl8Nkeh3v8gwHMNAuvZkXKUSBwCvhkghBBCEg4XA4QQQkjC4WKAEEIISThcDBBCCCEJZ2gB4WgeRX3L7QXd4aMRzd59Wvi2awYNdZotLW4JByhUmpvX65aVHoo9TITirZtu2q3a7Sbuf9Gq2lfKowipWtXmH901FCL2HF4PFy5ood/oGA75Q4dOqPbUnu0QM7ltQrVTDhORzpoWAEUOB5xeBt1U5izTimCAJzJ5QAtBZQzFRp7lcWTQR2dTKBXwemayVqWvHs6dsiW2HCtWIWZqSm97rYRj3uxrgVV7DedgJcLrOWJVXrtup8PUqqm3XbMqwYmITO/bq9pn5lB8msriuY2X9bnt2H8VxEhFVyXNyT9ByLOeok21to/hGHlGz7mUw9Sr2UTxVmhVhEzncNt7d+3S2+ngtU5Fej60WhizGZTzeD62uVmpgPPia61Dqn3mdB1ilpv6HCfGcDu1qp4DYYjztFBBY6S9V1tVXoNZiMlbOuU9+3EOLs5qcVxjHp9NywtYiVVyWux71U17IWRq94xqu8x6goEWTHYcc8c2Heo5fhF0u65qg/oBOXCYgWUs4zhXVdS09bsgiBxlJIeAbwYIIYSQhMPFACGEEJJwuBgghBBCEs7QmoGx0T3Q52Wswg4ZLPYyNq4L3GSzyxBT8Wuq/dAJzKl+8y6dB8lkML81P8Btm+06DzMxhZ87bRkKRQZzYEZ0/nZiCjUUBw5gEabVNZ3TXF7G/FbHyhVdWMTzuOb6a1Q7k8HCF/lRnTsqj+K59nIT0OdbxV1WmqiHSFubaufQfKQfaWONrDiMiTaB1WU8n/KoTlh2XMVWLBMW4zC9yWR1Ti8Toj4hndO5wYxjDR46+sarWrPwiufvhZjcuM6Hn19A45a20XNwdBINYDIOXUXQ09dztnEGYiaKNdW+9VXPxe00rXxxGzUL7ZbWA7T7mJstFrHwVtfKz5o06gqKlunS2ZMnICZf1PPBz2JufDMwGXxEG6Pv/amJGsQ89wU3q/ZSA+/X+qp+zvZX0RhntKTn7syu6yBm4DAdWq7r55yrwI9nFT2anELDrN3btQbmji8/hPtaxG2L6OT6gw+chIjA8ubZNoP7t58LqRRqWTod/bxeXcNn/IijOFYYaJ1Kp41agyirn0GlIu6/P9BzvrdBvQvfDBBCCCEJh4sBQgghJOFwMUAIIYQkHC4GCCGEkIQztICwLSjSmNmhhXajYzMYs02LK9pdFKnMzevDOPoQCjDOn9XrlqkpPB4TYbWmww/qylxjo2holMlrgZHx0JgnCLUgJTS4/1BQ+Ci+/lx5xFVVTW+r3UKDirPHtHgrm0eBUy6n9zU2hiYeIiimG9upx9b3sWphO6s/l86h4M5YQhYJNmZ+cblJebjm7Q/0sdmV/UTw8HshOn4M+ta1q+McqOa1CGt03CF+dRintC0B42jFUe0v0NdlYf48xOQy+vxHR7ZBTLGM17wbWBXrBihMWlvWVQqzjqqBxYoW/qULKL5tdvR8qo5hBTdP8L5sz+lxq9dRnBgceVC1RxxV5exKjtkcihU3g75jzqV8LSDs9VF4VizpmJEJvOZBpK9DY3YOt5PTz+ZMCZ873Y7DUCerq1Cm+wWIGXT1vZMv4Jjbe0unHK47KdfvAt3XbeG9c+jb9+vPhNdCTKlsGfqEONb9gf69s+oQa3bb+Lup09bnkkrhvIys6x9E+Cu7aI3b6NhuiBkGvhkghBBCEg4XA4QQQkjC4WKAEEIISThDawaiFOYL01YuNJ1DM5PTVlGUxVnMnZw/p91cZufwsDpdHRP0MQc0OYl5seP36Zzm8vxJiBkMdF5mcQ7z6n0rHd4IcTzm5tEsqL6ic8gT49MQk8rqc8v4mBvtruo81Oxp1F6UynrccmnMwUWVEegbzOgcdjCGnwssPUDakTvzezpPN+hsDc3A6GgN+uYaushWkMYxL1qGOp0QXYeOHdMGNpkItRS1st72aAVzg8bg3D2/oI9xzMN8aVa00VexhteuXNT599EianuKJTRcaQc6/2/EkQtt6msepTE3HFr31/xZLFoTpvSzpFqtQczqEuoBPE8/T6IQ88erDX0/+1lH/toyXeoNHLnpTSB06KC6Hf1MMREakKWt+VxxmBdlM/qccw5Dm9Ay7wkjR/EzhxlX3zIZ6rTRDCpv5cgrOdStXDih54of4HOnXMBjalu/L/DuFulYOoLzp1EzsXOv1lV4Ps6LtqWZ6HXxubdax98pnmVkNzaOhnC2fK21hs998fS5VkZwfg8D3wwQQgghCYeLAUIIISThcDFACCGEJBwuBgghhJCEM7SAMFdEYc5yU4voVnsodpm7T4uO1pbRcKXf0+ZFoZeDmHZPi4dWGyjCWgxx//VFvf9ux1FRqqLNec6uopCkUNRij1IFRRrHji5CX7elh7jho/BwxPIGWq2jSMT3tLgnaKNIpRNoccvR+05CTGYHCsVGd2jhTpBDQZJd4stbRSFNd1bPkdaqo5rY87DrStPu4jW3hWc1h2BtcruuCOg5xIGNE3eq9kgR56WX12vuvsPQZnQ7im+7KW14stRAQ6MJX8fMjKGp1rglTMpnUKjlZXA+V9LavKTZRIFsz+ixbSzhGHU6WjwWOkygalNaQBk5jL8yDpFjJdRztTqBIqxOoEWzK3WsrppK6e1ks457YBMY9PE+M9ZjLgjQ9Kc/0PdeoYjX1/cswbEjpm9tu7GGY2cL4UREQkvg3W7ivLCNiea6WHFz2TKVymVwXpg0GiH5aT1Ia46KgCWrUuWSo1ps5OvPXXXNTohZW9C/Ywp5R+XSFP5uGvS18C+Xx997Was6bTqL55/P6fOv1/E8hoFvBgghhJCEw8UAIYQQknC4GCCEEEISDhcDhBBCSMIZWkDYaqP719ycFsxl8ihumF3QYoqsoyJesVRT7XYTRSrdnhag1Bfx0M2So6paUwtgsmkUd0xNblftpWUUEHZ7WiRSruF21uro0BYMilYMOnFVSlp0lknhGq3T0ueWzziqqlnKIrsqmIiIN8C+INDbjgYodgmtcTx751mIGdT1uYY9FNNtBt02Cu/yeT0PMxl0XysWdN+2SRSwyYoWp1VxWsjYNi2QLdZQLBgMUIR1w7Selysrjnm5pgVO587WIebCeS3CmpichJjyKAp7F5e1a9qa477sD/S8mJrEioRjE7rP2Ao4Een29BxMpXB+ZydwjM4eP6TajSbegwOrJGHXUU0z3dfnkXLdX5uBwWdBPqeFd5kyCugio+eF56NNYGSsMXe4FMKI91Cs2FnF+8syVZXxAlZQNdZlaDXx2ZjNWRU/S3iDtR0ujb1F63dTweHAmNfXuGAccy6rBZy+w4Ewa4kafR+vWcrhcNrt6vEf2Da3ItK1XFzTGdz2iOU4aFc7HRa+GSCEEEISDhcDhBBCSMLhYoAQQghJOENrBuorDiMDyxhkDdN10m3p3GyUw5zLyJhOMKUdZbByeX2oxTRqDyYdFfmylsHJagPzMh3L/CGdR/ONRkMbYoQe5i8zWTSN6Lf0GA0cOfumdUzTOzDvWk/pGFsLISKSz+scve8wTkk78oLbK7qq3ZqjIuS5szq/NXsYL3aur6+JLxurnnW5qTiuSxjpa77kqDhZsPKTpoM587S1nM475s72mb2qXR7bBTGHDz8IfYNQj/H0Dqw2WC1q/cFqA4/x0CGdVz90+CjEZByGJ56lXSmX8J7bs3uvam/ficfYsvQusxdQfxQGev979+6HmEEXzbjs8Z5dwOu4aJk19Q2eh/2ciKKtUbXQ9fdaEOi5m7InoYiIVeHSCJ5Pf6B1BVGAz4vIehZnB2je4zmq9HnW83FiFKtyNhp6Xpy8cA5jrGqtI5a+S0SkHeL519taYxal8HeKbxn67NiBFWVNoPffcczB0TE9n2wDKxGRRh11FTt3aYOw1hpq3lbq+l4ZH0fdUtMygspmUEMyDHwzQAghhCQcLgYIIYSQhMPFACGEEJJwuBgghBBCEs7QAsKFBRROiNFiuIkJFGBEZW1m0lhBkUjQ0uKhUq4CMVFVC/F2b0OR3U37r4a+B+87rNpnvn4PxIQLF1S76jAU2n1AC6OuuxGNW779DRRmNRe1uKaYRSOeXl+LXQYemmiMTmuhWGtwHmKq27SYylWFrOPhJR+3BDidEyjwWjusjWs6cyhSKVa0aYdtmLFZFHM45ibQgsyoh8d67ze/ptrX7sOKeEFfC6qKJTQUKo/oeyDlML5qt1Hg1VjVxikuYVK3ZVXtc1RfvPHJN1v7wgpyxsP92/vLOIRJOcsUZnEJhVJz83o+3XfvYYi56uD1ql2uoAnSShfFkZFlYFRwCDiv3qarLy42HOdqiY9b3Y0Zt1xumi6jp56+F31HRbxqTY9DoYT3fT/Uc77XR3FzuKb7+ufrEJNpoTivNq4Fg2lHAdNqUT/nd+5EYW335CnVbjnu01XHpWpYJnUDg8LxvlVB1l/Ag6xZVUhLZbx3g1Cfv22gJSJSraFotVLWz4pGDq91vqivW62KInnbEC/lD/1rXcE3A4QQQkjC4WKAEEIISThcDBBCCCEJZ+jkgsvkZtDXhUwwoykigc659FcxL9PwdM6lWMUcbzatc2DlKhZ+aAVoOHJ+WZsFFUZRj9Ab6DxU1+AxTmyvqfae/ZgbPnUEi/csnKyrdjaD5+ZZ5hdLK3WISWd0zis/gvnbbbv0MYYejtFYHo/bLOpc1doh1CMsPaA1I4OmIw9f0Mc4MoLFfzaDlSZqIHKtWdXOpNB0Z9TKh1eLGLPY1fm6gcOwybMKl3iO3H8Q4br8wpy+LuNTaOjTbunrMjvnME+yCrJkszh3XAVQBqLvy5XlBsSsNuqqvdZ1FSvTn2s4niV9y+SnF2DetdtD3VK3axUwc5i7hCmrWFkO52W5qgvp5MuYh98MHDWdxEvpOZbN4ZgHkZ47xmCuu1LWeez+Muas68t11R4XvO/HHToNM9DzaRCiTqVi5b+n9qNmYGpMP69OL+D1veuh49AXhHo+dQY451JiFXZzCBsGvr53mk28vwcDfW7tDp7r9DYs1CTW/ms1HMexMb3/dBqfHYO+fU1oOkQIIYSQDcDFACGEEJJwuBgghBBCEg4XA4QQQkjCGVpA6KpqVtu5U7X9FApZpKd3MVFAkUjQ00KKrO8Qp1lV5pZXUOzSaqOxxJGzZ1Q7n0VjJC/Sgou2QyQSrOltmzUUm5TTKE5Mp7V4LZXBql85S6QSrKJIxC/rY7r52U+GmNqkFgStrKLYptdDRdLh+46p9sJZFG+ZQI9RNo3Xum1Vz8pkt8ZaM3SYcISWqK9UcIj6LCHO8soKxPhWdbbI4LgMIj3mvS4KjAYOM5VCRl/Pow+egpid27U5T+CotrewVNftRRRUdrtYhTLo6znvMj3K5LToqTfAezfl6XGcGkNDocAy3ur1cO4aQRFYaBnlFBzPjq71rKjsRPMosar69R3GMZuB5+P1DHr6GTIIcFzSfT0P85aIVEQkDPS2XRVVC3ktPJwsowB5m6ChTrentxW4qgZm9X1pG3iJiBRz+rjH8BErUzUUhLYHui+Fvxokb5lo2RUSRUT6Pf3BbX4NYsYmdCXBsTE0xMs7jPRyWcukrYcCXWMscX0Rt5OynmWho4rjMGyNpzUhhBBCNg0uBgghhJCEw8UAIYQQknCG1gzsvgpz/eN7dO4vncPNjZV0fm56dDvEHL1X56wf+Oa9EONFOgeWyWCequQo4jA2o/e3tOBIHllGMb0m5gsXZ3Xu5vTxeYjptjEfb0QfdydwaAZy+rj7joIhk1Yhlf1XHYCYINK5w8V5h0nMIhq3nDujc8jNhkP7YRXXKVXR2MLO+dVXcf+bQb6ERaUGWZ1T7KTx2uXS+hxNiDlF389YbbwHjFUcatlhKnX+1DHos42Qxicw196ydAx+Ds1ljKdzk6l8DWK8Ls7LkpVTzTkKPqUKel7mBfe/ujSn2r0GzovJq3UxIRPi8TRX0FCp39HXbaI0BjGhZbiz2sc8/Mq8LlaWL2GOfTOo1xehL5XS8ylyGBNFob6Hlx0FpPyG7vNSeH3HxvV4ZkKH9sBRj2y8ZJnsOH7TrFi6jAXH82JuWT+vu3082T0zmKMPRB/U7CoeQLag50XOUUSuuawN2AYDh7Ynr/P4MzOoSzMOU7FCQY/l2hpqcnp9fY0i18W2yGSc9n+XhG8GCCGEkITDxQAhhBCScLgYIIQQQhIOFwOEEEJIwhlaQHjVkw5CX9/T4o5iBcVD5Yzu+9bdd0HMt758j2qvXECh0JhVbXDHPhRphC6RRlmbooymUJzXWtZClsEKCuiWrEprZx3HWK6iyLJY1dtuNtG4ph3qcVyooylMeq8WTKbKaD4RrWmxydljWH0w6DgMjSxDocBRea8bagFl6BDb5Czzj8ig0chmYAv4RERCq2/g4dwZG9FjnO6h8GzNKivXbaFQa23VMp5KY3WyHbtQBHXqhDbMqo7vgxgJtVCr6xBz+ZbpT3eA4s+JMRTslSMtNk05/nTIlPQ4XujgNS9OaaOa7ZM4d8cndEy3jWLNhfkF6FuzquOVp/dCTK+n53zLcY3alsFStYpCxM3AGJxznj1XI3xeNS0RdNdharVtWo95sYTXxbcMbFoDFGCXi1iRzxbatZpotLVsmW/NL6GR3JJV5dYWRoqIFCI8t9GSfhb1I5yXgVW9c8cuFLd7M1ogu+oQsRYL+vzHRvF3UxDg752MJQT1HNc6ggq6eB6VEX2MdpXUYeGbAUIIISThcDFACCGEJBwuBgghhJCEM7RmwM9grqZiFV/I59CQ4tQJXVzl61/9OsSsnte5SX+A+5o9P6vaPYM5qOnte6DPs4on+TmH6Y/lVeQNMKfbH+hczWoLc0BBiPm0KKXHZHEV80L5ms6/t0tYFCpjGWssOswvgobOE/ZwiGRtGY8xZZnSdB15wdBOMxdw6qSKOijtyNNtBi4PjqqVH43SmEcfWMVyOo06xPRDfT17XTSs6rX154oTqK0ZHUfDrIHZodpLa5jr9iK9rdqYw2DJEhK0u3WIyafw3i2M6D7TdxSwMnpwi44nysDXMZPbd0BM0TLVatZnIWYQ4HzKVGqqvRShluXUnDbuma5izHhN588LGbwem4Gd+xcRqVT0IBeLaMCWzehniHHkmiOj/xbsdfDZGFh/L0Y+3kydLD7TOm398Gm20eysZRVKCjx87qcyeg62HQ+1pXMXoK86VlPtmXHUgAzy+lxSaRyjfFqP41gVdTvptD7GMMC/sfs93HbWMraKIhzbSlnrEVzFuopF/QwIQ7wew8A3A4QQQkjC4WKAEEIISThcDBBCCCEJh4sBQgghJOEMLSC8cBoFPTuntclOr4WitqKnzR9mxtGQId/WQopKHs0ven1tQtIRNCWZm52DvmxBC8MKNRQH5nyrepRDeCeWYDGXQRFYo4GmGd2BFnM0mjhG1b26YtuNN9wIMVPX6bFeS6MI6tx5bcqy6jCACT0UynUCfUxhGoU8pVF9HSszKFTrdvQ1MV1H9cNNYHX+HPRlrXmQG9sGMa2uFlLObEdTKUuDJUEPTUkiEFJi5bHtO3dCX8aqwLewiuKhkyd09cyi4zzyZS0wm9iG92C/j5N+xdf7K+ZwPnmWoKwYosgxZYmPS7UaxIgl9HXVZsvkS9DnWYfdbaOp12hFX6TJSbx36w19rTsOseZmkEmjOBAr4KFgLJ3RI9hqoziwu6j7TITbKVuV/aqOyrCnHWLPfKR/tRhHEcgw0s+iWtFh9LSsj+noCTRSW23Woa/T1XP3+idfjdsu63H0S/i3cSrU59Fporh6xDL9CQN87s3PYfXJTlkfYy6HAsKRkZpqD1yVU+3d0XSIEEIIIRuBiwFCCCEk4XAxQAghhCQcLgYIIYSQhDO0gHDhOFbS21e6SsfMzUNM5GsByI4xrAwVLemYtEEhxYQl3vJRYyiNOoqHTp88rdrNJkqTJsa1u5/vo9gmY1UK8wMU2ywv4hittiwHL0eFsVRWC6NueMb3Qky6psekncF13GJXuyLOt/A8OmvY51sisJ6PIkc/rT+XzuP5VzP6PFLFLbLWbKOor9HWzm6TBRRkFgpaZBhlUMBmiqOq7fkosktZDmXGUXkt7dj2cl0f9/kldHHrhPqaHz11HGJ2bNf3XM7hHil5FIZ5kR4jE6HIcK2lBU0lQce8QkGf28oqCm1H09ZccThCprIo/Mt3tdCv7NUhJp3T51sdHYUYEX2tF5YajpjHn7TDGbJrVfsrOhxLg9ASBzpEhoOBfhaGDldTiXRMKof3Scph8Zmz3CvzDsHzWl3PlfnzKLKr5LTYdWbHbogJL+B89n19X/Q7OHfLFX3NPccYdXpa5HfmLP6OO7CvpvfVQ3faeUfFzTDQYzs5iQLKnlVtslTGe6BtndvKCj4nhmGLPK0JIYQQsllwMUAIIYQkHC4GCCGEkIQztGagPYe55gfXjqj2uTNoCNGJdE5x7wGsWDawDCJOncbtTPdmVDs7jjmotMFj7Ld0XqozwM/Z5f3ymK6UgpX/7rcdzkQBmsKIZVrh2S41ItLp6M/1HY4ruYo2H2l20HzCK2shxXIXDTJaIR73tpo2EBqtYf46VdL5tXQWD9Jv65xba3VrGLdMzMxAX6+h8/GBw2kqPaInwpLjfJZW9OfGcq5bSmsEMo786UoDr9WSdYwlh66gMK6P8b7Dh3D31n2xfXIKQoKB496xTGg6jsp35ZzOV+czePMsrmmNQLd9EmJuqt6g2k67qj6OUdboYzJdvAet1LiMjTgqElqmS+ePoYHZZjAIcF6mLFOwbtdRidWah+011GnYWhbPw7nb6erxjZbxeLJ51DUYT1+HwjYc87Cp76dUBnPtkej97dmDhlnlEbwvFuZ0JcOGwxAv09FzNW/rVkSkkNfPvX379kNMzjr/yOB55Ao4o8tl/bleD+duz6oUGgQ41r5vXbfI4fA0BHwzQAghhCQcLgYIIYSQhMPFACGEEJJwuBgghBBCEs7QAsJ8Ds0Ojp0+pdqFNAoXAqtK38BRSW+0os0WznTOQMzygjb0KWawmtfIBJpvRDmtHhoto1tR1err9VAo1mxqwV4QoLlK1EfzjbQ1xF6IIpHGshb3zDmMLbwxvW7z0jiOtT1aKLftxoMQ01xDA56Duw+o9kgWxT6nzmlRZ6eNgpy1c5bZhUsJuQmkimgy41uVxYxxGQFpgdEFh+nP6dNaaOZvw/ukaYkTMyU0Nwkc1SS3baup9uqco1Lnor6erVU03hqMVVW7ksf7pN/GOX/fUX1/pzJ4fx/cqask+uN4fwWWKU0mhfOisaJNfnIOsWIU4XH3PC3G9B1iskGgt7U0j2K6+rJ+vlQKeC9vBp6HY1W0KgkGId6LLUs43e5iTMnaTj6PFV0Xl+q6vYDmOaUKPi/saq2eQxJaSOlrNzo+gdup6/Ofn8cKiZGH82KprueT76gWmynWVDuVx3s3bVUAnJ5GMXIY6Gd8GKHQdXwC7wsjWmg4O4tjm7eEh2stfAaVS/r+zhfxHhgGvhkghBBCEg4XA4QQQkjC4WKAEEIISThDawZKVUchlVWdl8nmMO8ZLeu8SH0F83W1ks45lXO4r2Cgt5MvYH4ryGF+bed1O1XbW8N87fYxnVPutnDbcyd1vrbRQvMN31GEqD+wcp8err9Sns5PrsxiXj8/oy9VbQfmoLITetzGDmBRqOwqGt5kKjpXNnsO886zc3XVTns4RvlcTbXHJ2sQsxmcOn4K+mo1rTmpOIqErFoFR06dx0JU3UjP+dLoNowJ9Zifna1DjJfGOb9tQh9TPsTbNfL1/p85PQkx5ZI+14JDNzOSwrzrDksD46Vw/33L9OfB01hsplrWc6XquE/PPKQLLI3VxiFGcnhufU/vf5DBeRlZBlkmhc+pvq+v0Uq0NfQu2azjfKxHmBniWMdqOL+bVh691cJnc8cy6+l10VAnlcZ8/Eik504QoAbDzvUP+vhsbltGPF7KYRrnMHKrjeo8eiSot6nUtAZmpIr3wGLdytGvoJ6rOqJNvFZX8fmdw8soA8sUru3Q7QxCPSZ5lyOepXdKZx0xQ8A3A4QQQkjC4WKAEEIISThcDBBCCCEJh4sBQgghJOEMLSBcWUTxVNYSwzWXHIYnlvnFhTPnIKY/pqtu2VWgREQ6fS1WbDmqBuaqKOA7uF9XSYxW0BCiYZk97NqxB2IiS8hypo6Vwmwhh4hIX7QApDCG51aZ1OKxokMcGfa1SKfjOP98wdp2FkU7mTIK1VbWtHClH6BI6Hue+jTVzmXR9KlpCQ8zqa1h3BIEKEzqh5boKoPCpNOnjun2CRQiVspaqDTlME4JBnXVzpXR3OSko+Ln8oIWPZVSKPzLW8YxkcOsZ2AJzBYc92nkEN5NTOhz8T2c37Z2rS8oXlqY0+cWZtB4K5/Vj6Kzy2g8lnFURCxPaROY+qqjmmhab7tTwWu0Zk35lQHOmc2gvoKiMuPpg62UUfiWSusL02mjSdr8nJ4HjQbua3JCVwmsVlHYWa7gvOy09XO2kXJVWdXPq0oJzcGiUG9nrYvivOpIFfpq4/q+SGXweV2phVYbfx12LQFf21HdNNfVfekM/o2dd5hYZdN6Po9POESea/p3k13FUASroLbbONbDwDcDhBBCSMLhYoAQQghJOFwMEEIIIQlnaM1AwWDOI2UlDPsBmk9krV2stDAvtSw6D1TKYl49k9N5kV4Hc/8pV2EczzJ26DQgpNnU+zdmB8Q0VvVxt3qYPxXH7sOMjqvMYM6+bBVYqlax8MeY1ddYw7zvfF0XzQENgYjM7MRz89Z07iy3A6dFxTIUWpjD3F1oFaCZnkGTmM0g4yjc0bPMoDprmIubGdF5x+J1qCVZW9WfWz7xAB5ApM1cRrejPqHZQMOX0JoGGUduOLDW8/Z9IiIyWtO52MYC6n+aDhOtUkHnNLM+zvmGVbBq2iquJCLSNnquTjocWPyczjsv1/E+7TXxuNsNbXJULWP+uG903vfo6QsQE1pOPtk0amI2g7lZPGdb3pLPYR6/19c58oUFfF50Ovqcc465YxdK8lM4B2ZnUe/St4r1jNbwWXD6hM6H7921H2K2TWlDn7FteH0rDh1UJmNpUM4fwxjLVKsY4XNv0LeeE44CbUFfPwtHHMWyqtUa9IV9fe+mU/i8Fk8/X7IOHVjOup86XdTkDAPfDBBCCCEJh4sBQgghJOFwMUAIIYQkHC4GCCGEkITjGWO2RnkuQgghhGwKfDNACCGEJBwuBgghhJCEw8UAIYQQknC4GCCEEEISDhcDhBBCSMLhYoAQQghJOFwMEEIIIQmHiwFCCCEk4XAxQAghhCQcLgYIIYSQhMPFACGEEJJwuBgghBBCEg4XA4QQQkjC4WKAEEIISThcDBBCCCEJh4sBQgghJOFwMUAIIYQkHC4GCCGEkITDxQAhhBCScLgYIIQQQhIOFwOEEEJIwuFigBBCCEk4XAwQQgghCYeLAUIIISThcDFACCGEJBwuBgghhJCEw8UAIYQQknC4GCCEEEISDhcDhBBCSMLhYoAQQghJOFwMEEIIIQmHiwFCCCEk4XAxQAghhCQcLgYIIYSQhJPIxcA//qOI58X/XuSNbxTZu/fK7/u5zxW58cYrvx9CNnWik8TwRJhm7353fIxPlO1uBolcDFxOfu3XRD71qc0+CkKuMJs50b/61fipW69vzv7J4wafp5sHFwP/jz/+Y5EHH3zsn+PkJU8onogT/atfFXnPe7gYeAKx1abZ//f/iXQ6l3+73008oRYDUSTS7V6ZbWcyIrncldn2400QiPT7m30UZMNwopPHgSRNs3RaJJ9/9JgrOR5PBDZlMXAxz3L4sMitt4qMjIiMj4u84x36YnieyNveJvKxj4nccEM8uT7zmfhn586J/PRPi2zbFvffcIPIn/wJ7uvsWZFXvUqkVBKZmhL5hV8Q6fUwzpXjiiKR3/1dkZtuiifS5KTIS14i8s1vrh9fqyXyoQ/F/+958XYucviwyOnT7jE4dEjkec8TKRZFduwQ+a//FWPm50Vuuy0+x3xe5MlPjvf1cE6ejPf73/6byPveJ3LgQDwehw7FP3//++OxKRZFRkdFnvY0kT/7M72NYceSPEaSPtG//nWRl70snnilksiTnhTv5yLf/na8nf374/1OT8fnurSkx/Cd74z/f9++9f2fPIn7SyhJnmZf+pLIj/yIyO7d8XHv2hUfk/0WwJXbf6TxePgz9Xd+R2TPHpFCQeSWW0Tuu89xASw++EGR5z8/Hp9cTuT660X+4A8wbu9ekR/6IZEvf1nk6U+Px2T/fpEPfxhj63WRn//5+PxyOZGDB0V+8zfjMb1cpC/fph47t94aD8iv/7rIHXeI/N7viays6MH4/OdFPv7x+KJNTMTxc3Miz3zm+sWcnBT5u7+Lf3GursaDJhJPiBe8IJ5Ab3+7yPbtIh/5SLzNYbjtNpE//VORl75U5E1viv/i/tKX4mN92tPibb3pTfGFfMtb4s8cOLD++euuiyfQw4U1IvE5vuQlIq9+dTwGn/ykyL/7d/FN8tKXrh/7c58rcvRofI779ol84hPxzVGvxzf6w/ngB+Mb/y1viSfL2Fj8qu7tbxd57WvXHwzf/nb8jP7RH40/N+xYku+AJE70v//7+Ek3MxNPvulpkQceEPk//2d98v7934scPy7yUz8V//z++0U+8IH43zvuiM/71a8WeeghkT//8/jJPDERf3Zy8jFfhu92kjjNPvEJkXZb5F//63gB9I1vxH8AnT0b/+xSuMbjIh/+sEizKfLWt8bPzt/93fiX/L33xoumR+IP/iBeXLzylfEbib/+a5Gf/dn4F/db36pjjx6Nn8+33SbyhjfEC7A3vlHk5pvjbYjE53fLLfGC7Wd+Jl74fPWrIr/0SyIXLsR/BF4WzCbwrncZI2LMK1+p+3/2Z+P+e+6J2yLG+L4x99+v4267zZiZGWMWF3X/619vTLVqTLsdt9/3vngbH//4ekyrZczBg3H/F76w3v+GNxizZ896+/Ofj2Pe/nY8/iha//9SKf6sCxFjbrlF991yS9z/4Q+v9/V6xkxPG/Oa16z3XTz2j350va/fN+b7vs+YctmY1dW478SJOG5kxJj5eb2vf/EvjLnhBvexXWTYsSQbIKkTPQiM2bcv3s/KyiNv0zW5/vzP4+198Yvrfe99b9x34oR7/wknqdPMGPcU+vVfN8bzjDl1ar3v4hjZ23ONx8VnaqFgzNmz6/1f/3rc/wu/8OjbdR3Ti19szP79um/PHpzq8/PG5HLG/Jt/s973K78Sj8tDD+nP//t/b0wqZczp07i/jbCpmgF7lfRzPxf/+7d/u953yy3xa5aLGCNy++0ir3hF/P+Li+v/vfjFIo2GyF13rW9nZiZeeV2kWFxfdT4at98er5Tf9S782bBfJTEG3wqIiJTLIj/+4+vtbDZeDR8/vt73t38b/7H0L//lel8mE6/I19ZE/umf9DZf8xr8Y6lWi1fI//zPj3x8w44l+Q5I2kS/+26REyfiPylrtUfeZqGw/v/dbnxuz3xm3ObEe8wkbZqJ6CnUasXH/axnxbF3333pbdrj8XBe9ao4hXuRpz9d5BnP0OPp4uHH1GjEx3TLLfHzvdHQsddfL/IDP7DenpwUueYa/bvgE5+IY0ZH9fV54QtFwlDki1+89HkOw6amCa66SrcPHBDxfZ0O3LdPxywsxK/JP/CB+D8X8/Pxv6dOxbkVe7Jdc82lj+3Ysfg12NjYpWMfKzt34jGNjsav8C9y6lQ8Pr61XLvuuvWfPxx7nETi1MPnPhdP4oMHRX7wB+P0wLOfHf/8sYwl+Q5I2kQ/diz+91KGGsvL8bcE/uIvcKLZT01ySZI2zUTilMUv/7LIpz8dp0QezjBTyPXcvIg9niIiV18dpxUeja98JV70fO1r8St++5iq1fX27t34+dFRfS5HjsS/Gx4pM3a5ntGbuhiwca0QH77KElkXTPz4j8c5FhdPetLlPa7LTSrl7jdm49u0x0kkXjg8+GCcpv3MZ+LV+f/4H/HN8573fHeM5ROSpEz0S3HrrXHy853vFHnKU+JXZlEUC2oupzIqoXy3T7MwFHnRi+I15b/7dyLXXhsLG8+di/Puw0wh13PzO+HYsVhXce21Ir/927HgL5uN3yb8zu/gMQ3zuyCK4vP8t//WHXv11Zfn2Dd1MXDkiF6ZHT0an/ijOVdNTopUKvFEeOELH337e/bE6k9j9I0xzPdfDxwQ+exn44n2aKvZK+U+tWdPvBqMIv124PDh9Z8PQ6kk8rrXxf/1+7Ee61d/NRafPJaxJN8BSZvoF1Vf9933yMe+siLyD/8Qr0p/+ZfX+48c+c72nWCSNs3uvTfWln7oQyI/+ZPr/X//98Nv49FwTcWHHnr08fzrv46/XfHpT+u/+r/whY0fx4EDcWr4Sj+jN1Uz8N//u26///3xvxcV9S5SqTg/fvvt7q95LCys///LXiZy/nys1r9Iu/3Ir8MezmteE0/697wHf/bwVVup9MheKI/21cJL8bKXiczOivzlX673BUE8RuVynIO6FA//hpZIvEK9/vr4+AeDxzaW5DsgaRP9qU+Nfyu97334mYvbvPgnkf06zCWNLpXif2k69KgkbZq5ppAx+tur3wmf+lT8luEi3/hG/E2sS42nfUyNRvxtr41y661xyuGzn8Wf1evx74XLwaa+GThxIv76xUteEp/sRz8a57Sf/ORH/9xv/Ea80nrGM0Te/Ob4F9zycix0+dzn4v8XiX/2+78frxrvvDMWv3zkI7Ho5VI873kiP/ET8ddzjhxZf3P5pS/FP3vb2+K4m2+O9/nbvx3nxPbti49L5JG/WjgMb3mLyB/9Ufy6684749XoJz8Z56Pe9754NX8pfvAHYxHis58dfxXmgQfi8Xj5y9c/P+xYku+ApE1034+/X/WKV8Sv/3/qp+JjOnw4/trgZz8bfxn+Oc+JDTYGg1ip9X//bzxWNjffHP/7H/+jyOtfHytpX/GK9UUCEZHkTbNrr43/av7FX4x/aY+MxIsaWzuwUQ4eFPn+74+/ttjrxc/d8fFHfl0vEj9zs9l4ev7Mz8R/0f/xH8eeAxcubOw43vnO+E3DD/3Q+tcOW634zcgnPxlrQi5+4/Y74vJ8KeGxcfHrGIcOGfPa1xpTqRgzOmrM295mTKezHidizFvf6t7G3Fz8s127jMlk4q/mveAFxnzgAzru1Kn4KzfFojETE8a84x3GfOYzl/4qjDHxN6Te+15jrr3WmGzWmMlJY176UmPuvHM95vBhY57znPhrKCL6azGP9NVC19f9XPufmzPmp34qPu5s1pibbjLmgx/UMRe/BvPe9+I2/+iP4mMbH4+/rnLggDHvfKcxjQbuZ5ixJI+RJE90Y4z58peNedGL4vMulYx50pOMef/7139+9qwxP/zDxtRq8XfYfuRHjDl/Pt7eu96lt/Urv2LMjh3xd8H4NUNFkqfZoUPGvPCF8detJyaMefOb469Siuhn5SN9tdA1Hg9/pv7Wb8VjkssZ8wM/sP41zUfb7qc/HU/1fN6YvXuN+c3fNOZP/gSn7Z49xrz85bj/W27B82w2jfmlX4q/xpnNxuf6rGcZ89/+W/yV88uBZ8x3IlvbGO9+d/y6aGHhMq1oCNmKcKKTxwFOs8vLyZPxG4n3vjd+65AUnlC1CQghhBBy+eFigBBCCEk4XAwQQgghCWdTNAOEEEII2TrwzQAhhBCScLgYIIQQQhLO0KZDr/7R74O+QHqq3Rug0bKBvg4eREbHPO2pz4OY8aqu6OAZ3FfgsGIKglC1M5kMxESWBaZvVwcSkTAMoc8m5eO2W1alil6vBTHFYl61c2m8LNmsjvEcMctL2iEo42EGqNfrQ9++a65Tbd/Hzw06+rh7HYy5wXI3GZvBot837HFU5rjCLDYH0GeseeFaFRvRE8NllTpMli2V0tcqDPF4en2cF0Gg48qlGsSk07lH/Ux8jPpcPceJGBkmW4gxnmW27phyElmfc42Z3Re5YlyHZO3fRC47Nmv/3sbqHuyY2b6hz30n/PIHHSXprLFxXU+xuxyD57pWEGNt+7IaQ8PGHPPSnheOExlm5jqPe4gxgvtiKybVhziP//zTl7as5ZsBQgghJOFwMUAIIYQkHC4GCCGEkITDxQAhhBCScIYWEC4s1KEvU9BCnEptFGJWW5YwKkQB22hFG2r3mlh2qj7IqnaugPtacNTczeW0wGpqago/Nz+n2kVHGa58vqDaLhFUupCDvsA635FKAWLGamXVPnPmHMRce/Cgai9cOAsxX/y/f6PaGYfIcHpyBvqe8tTvUe3CSA1iLpw9o9pe1ISY2bPHVHswwJKHmyEgdAHCJGchdT2/owivue/p9bQxKE47dvR+1X7g8LchptHEsZqfn1Xtgweug5hnP0sXOR8bRXP60OhziyI8Rtf52+Ip3ykgtMRsEIFj7RQQ2iI/1zE6tg0lkG01sOOg3Bowu/eySuU2jO+jUNo+VqeA0MIVgQJCjAIB4RUdlksLCD2ngPDyqPpcW/GeADY8l2vm8s0AIYQQknC4GCCEEEISDhcDhBBCSMIZWjOQz2Gue62jc/vpHBqnjIyWdIwpQ8za6qpu1xchZve1e3SHIzHSyWF+p1TU652s14MYu88PcTs5384NOzQDjpxyzuuqdj6dh5hsWpvCbJuehJjl2fOqXT99DGLKvmW44kjw7ZioQd/CmVOqnaugZiPsavOkQgZNmNr1C7rdRF2D/MCLsW8TsFPLrlxo2ktZMRjUaTdU+557vgExf/WpT6r23Q/cDzHZEt5frZY26Mp+4Z8g5h+/+mXVfslzcXy/9+naMKxSHYMYP8LctGdrJgwa+oAxk9O5xe67tOmQC6fWAAzDhsmfP3H+BnJpUGD87EHACPEdc9e3rt0wuffLmUIfTn9w6bkz1FY2eOBJKt3zxLkrCCGEEHJF4GKAEEIISThcDBBCCCEJh4sBQgghJOEMLSDMZjE0HWiTndUGCggjSy+Yz2YhJp3RfUHUhZgorKv2WAWPp7JzBPqy1v4GAQoISzurqu00n/C0eMpl6FPM4Cejih6AgeeoiGgJ/06fQeHd8TvvVu3pNAr4nm2ZB41MTUPM7Gk0NPK6azpm9jTEZNNayLT7wE6MydpVG4eeXlcUzzHmwxi1DPq6AmDkmDtHDt+l2n/xyY9CzD0PHlVt49h3uOaY81a73UXDrq9+61uqferkUYhZbWhh5y3PeznETEzi9QyDSxsK2cfoqu2JwrSNibKc1RaHKb23IRuWrWI6hHMXjXicVk86Zoh7YGucseZyHeMw97trWkZuq6utzQY1j3wzQAghhCQcLgYIIYSQhMPFACGEEJJwhk7qRgazgcWSztGvtVchpt7Qpiy1SgVixso6Zz+9DYsJ7dg2rtrVHBYTSjnyQhkrj+2ncP3T6etccBCguUo6rbeTduTyio4+yWhdxYVGG0L+4ctfV+2vfP0QbtsyoJmcrELMglXgaGmlATHhYAB9BSvVn+rUIWZ+SesYrrluG8TYGeSUh/qQzcGVRNN9KQ9Nd9o9PZ8///m/hphv3fct1W60HXMnow2FBgFeg3a7A32S0cfU72BMeUTfT/XGGsT85V/drtoLloGViMjLX/Yq6Nux90bVDo1jfkPO3jHW1n3hKv5im+s4057OGkR256Wv9XBsDbOZoXLdrs/ZZlBbURCw1bi09OKJwQavNd8MEEIIIQmHiwFCCCEk4XAxQAghhCQcLgYIIYSQhDO0gNBlbDHoNFXbNyiMGslroZ/XRSHi9HYtDrxp3zUQMzkyodomQDMI3yFMKqS0iM1PO4xLLPHS8moTYgoVXW3QoP+LrPTwmE7Ma+HdF+74JsQceUhXDWyvocgwb23aj3IQ47W1ELK5igLC0e3boa8yoitLFmYwJhNpQ6l8FvefyehrHYZbY63prHZnXfMoxHm5sjyr2t96AIWdtqFQp4v3gOfr28wTjKmMoLBWrM+lyiga7fb0dSmUsCroUlOLCr/01S9CzFgZBZQvr2mBcKG2C2Iio4/ROITGxrIiiiKHkYstIHRcs8jRZz+Xogj37zLueaIwjIDQacZkmw45KhuS7042eqWfuHcJIYQQQi4LXAwQQgghCYeLAUIIISThDK0Z+IGnPhn6en1tghIMsJBL18oh5h1mQftn9ugO9G2RudlF1fazuI6pVkrQl0trzYCr8ITn63xppTqG+19YUu0v/dNXMWYeDV/mV3X+f66BeoQgsM6lj4IEY6V0W10sCnXgwAH9GR+zR7lJLF6UTWlTnLnZFdx/oJ2Jen2cOr2BvnADh3nTZuBINYudWVtYwAJOf/aJj6n2N+6+C2KWLWOnXB7n4Pi41sQcexALUe3evRv6AssMq75ah5gw0ic3GODcKRe13kVyqCv40l3fhr6UVeTrlh/4QYipTRxUbT+H5x8F+hkQhqiZcN70sCGH9gNCHPe3dfO454Nmq+gMfEcGGAo/Oc4HTIcc296oodEweLZBleMY7SJTrsMJo8CKGfKY7WJOjkJNjg9BzzD7s+eTS+/iAoowbfBy2HujZoAQQgghG4KLAUIIISThcDFACCGEJBwuBgghhJCEM7SAcNuuGvSZQBulpFNoXNK3KrT5XgZiWkt11T55+ijErFgCvkC6EDOzHSvp7ZzWfRnH+qdQqql2r4dipjvvvke1778PDWhW8ZCkZ/T5ugQpUV/vz49QYNX3dMz5lQsQs2dtUu8rhVUDzTYc/2OzemxPzy3j/gN9cqlTSxCTTmvxVhg6BmRTQEGPb83VIMJr/q3DD6j2IMSYalkL5sqVUYiZntTXZW15EWJWVlG02VrR16GxUoeYolUFNOrgPegZbVbUWcPrct8S7n+1rsWRx08eg5ide25Q7R/+kdsgJm0ZVA0ChygOjIicijPo8i1hmOe4vw1Iqp445encYrCtZiDkuC6uCpcWttjTVRnXt0TQrqvkNFTakBpvgxUirY8NO5Mul4Dzcs0GvhkghBBCEg4XA4QQQkjC4WKAEEIISThDawbqKSyek7aMObwQDU+ykc5hLp+dhZjFszqH2l7qQMzKhXnV7nawCM/SSTRzWbbytZkBZnQ6oc66dAeYG16yzIJ8RzrcCx25UMsExnMUafFD3ZfxUTNg1YMRUylATCetr0e7i9fj8KnT0FdY0+MdOqZFxzJGGhyfg5gdO7ShVKXoKEizRbBnwUh1HGLKZX0+S45c//i4nl8Li6ilWKtbuf86ajKaHTSRMlbxpF07sVDQ+OSUap+dw/urVq3pY7zguAfn56FveZfe9tfuvhdi6v94h2qn0zgvb3n+i1S7OroDYoKBbQyE+eNhkqOu+wuKrLkK+4BZ0dbQELiP4nLZzFwuXGZQlumP41O+ZTrk+su0bxlvnTl7HmJqY2gSV6tp7c6wRkA2V9KYaavBNwOEEEJIwuFigBBCCEk4XAwQQgghCYeLAUIIISThDC0gtE1vRETEMtRJO8QWS+fqqr18HAVW3boWT/XqKKaKWloMF/RQENLq4+ey1jGWbCWeiJxc1MKwwEfjlrZlDNR1GNCEPhr65CyTpYxDj9JPafGSCfDc+paeanTfPojxrOp4J+5CY6RFHysr5ixt6FS5BjFnF7TorNlBgVeupM1tRkdxO5uCY8yNVQGvkM9DzK7tM6q9vIgiu35PD16rvQoxy4taMLh0AYWI2SzOnfFtE6qddxxju633n0rj/B5Yglioeici+dEK9GXseTBAYe/5+ZOq/b4/+G2IOfTA3ap9221vh5htM3o+ByGeh3EJ/yI9D31xVUS8NFh5bkObuey47ZEeu6jt8RbCQUVCR4xnzUP7WoqIXDijReGNOgrHp6ZnoO9ycSXHbaOixisF3wwQQgghCYeLAUIIISThcDFACCGEJBwuBgghhJCEM7SAMO0QJqVCvZaYt8SCIiL3f1W7lu0tY2XBqKsFdJ0Witx6XS1eavTRaWxNsC+V1gKrdK4IMa2BFh3VA7QXHKT0uYYB7mskg2NUsboyjuVX33JybDuM+/qRFrIcPnIcYgIrZqWPDoRLHTy3qbJ266q3URxpQi1eW2qgmGy1pavTpbJbw70LHOhExLfGyvPw2l29/2rVPn32HMQ067ZgEEVB23dOq3a/hW6e3TXs63X1tTo7h5UqMxmrKmYGhYgT45YQsYAugbtGq9AXWK58s+fx/AddLfpq9/H8/+YLf68/08dzffObfk61p3fdADGR4xrZFes8h9DZFmoZcVXHs3scgulN4cpVWPTxpDeGq8Ak9OBDzXbYPH8G3VHPWX1XX4fzolwu494cTpRbja3mbsg3A4QQQkjC4WKAEEIISThcDBBCCCEJZ2jNQOBjDsbOyxw/iYZC8wvaCGhfHvN1dk5v4GPMwNN9vRDXMasOI6Kcp3O6ox7mVFPWMPSjS5v+ZB15soyj2mEurfNCvmPbga/3n3I4ExWsanCO1L8cP3FGtXuOKpLdEA2VMqHeWDWPY7RY17qK5Q7mfc9ZRSO7N0xAzGbg9PawrkM6jec8OaYrEnqOtbOxNCiTY6iJ2b9rp2rfsP86iDnn0COkMlm9L6isJzK3oHUEq47rMgj0tWu2mhAzkhuFPmN/ro5anlp1RLWz2RzE9AJdee6f/vmbELO8+huq/bpbfwJinvGsF0FfKqXvlSjsQYznRVbbURHRrrLnGOvNwJ1W3mKmQ45N+3af47m3ZJl4PfgAmqRFVtXXrEOXNcy5bbX8/FaEbwYIIYSQhMPFACGEEJJwuBgghBBCEg4XA4QQQkjCGVpAaAYoqBlYxjurqygw8qxdhAOsKta3TEh6BgU+oaX/CEPcTugQzPWtaoN9h1mQWIZCLsGZrSdy61HwuNNpLQKLAjzuyDLAcUmXKlVdVW5yAoVqa1YFvXKAx1MNUeBVtAZ3uoLV8R48rtWB7VU0HVrTWjLprW0V45ZLEzlsUvbt0ZX0xmooshuk6qo9sw2rSXaa+roc2HMQYq7afxX0dQda2Dk9joLM+w5r0dV9Dx6GmFXLvGilUYeYwHE/eTVdBbPfwZjJST0m6QwaGq0t6/MPchjzuS9/Q7XPnjkPMf/BIWL+nqc8RbWzGRTIep5lGBY6bnBb8eY9cf5OGkpAdyUPwPHA9Cxh52oDq3ketgSDK0soQC9bBlmhQ6Q9DBsVEG61yoJXkifOjCeEEELIFYGLAUIIISThcDFACCGEJJyhNQMOHyAJrWJBQQ/zOb2ezuO3HUWIwp7loOPI04SenVfHA8o5CuOUqtoUZi3EY1wbaKOSKHLkpYyVd3Rk9n1HFaJ8Xg9xp4XbDiwdQ5TGvGcqp7UHPYf2Ip3Sn3P4fEi+OAJ9dkGaw8cfgJheoI1qsn4WYgpZnd+LBltjrelKF0bWoblsaGZ27VftG67HIim9u76m2jtGaxAzKI+pdq2KRYGW6/PQd+qovg4lH82KUp6+yGMOXYG/qnP24fR2iKkUsYDXwuKc3k4eB3Jsckq152axmFKvo+8vV84+7WvTp2/ffwxi/sN/ehf03fzUG1V7z95dEPOyF75QtQ9edSPEBFbRnK2SK/acAibd5w+TD3eEYNelz9kdgb2+1dVda0FMY2lFtSPHvPCsAnmpLJqDucbI7gMTpDjK1amPaYihxbny+M4dWw+x0bm7NZ7WhBBCCNk0uBgghBBCEg4XA4QQQkjC4WKAEEIISThDCwjTtuuPiNieNpFDhbXa0QLCVg/NatKW4UnKWTDMqv7nOPLp8THoG61qwcnZYwsQ0+jqY4ocw+JZarzIVsiISDrrEBAWLOFfF6uqiSWc6TpEjm2r8tughfvP57Wh0MBxQYoVFIpFgVWxLYXXaPt4TbUzIRoTVcsl1e70HOe6RTCW8M6l+ckU9Fi98uWvhpj9u7Rg7Z5vfBli7HlRLOE1KJf3Ql9gzctKDg2jOpbR1+m5WYgZr2pjoLFaDWLabRR4+ZZxzPR2NLrK57VotOuY36ElyG2vYEzKmqvZUgliHjiBlR0PHTul2qOTKM68935tbvOTP4YVEZ/9vc9Ubc/1gNkEfMfENN6lY2y8oRSEDkmhJUZzChpdWHGjIyhcrlZ0X3MVq2nmrZhCEeeFq8KkLRh0/9VrHqX1/7b9OBY7HEb45zZPsq7RBo+ZbwYIIYSQhMPFACGEEJJwuBgghBBCEs7QibGU7dIiAk4tnRbmHTtWLrDjKCY0am0o5TIlsfJZGYfBTzqFOfLAco1Y6zsKHFkJJkcKaigfiXIZc8HFotYMdFpommEs06VsFvPxDWtsQ8FxtHOHBr2LJAwdRaB6+vy9Lo6tl9VTZWwSzzWd0efasgonbSns6+lKqVrzcHR0GmKe8SxtaHPXP38RYuYXdJEn3+HgNT6+A/quuVqb4xw7ei/ENFeXVbtoHKZaq3XV7nQdBcUcc377thnVPn8BDYUajYZqj1ZrEFOv61xwOoXzK7AKeLmMv7JpfFx1W/pzK7N1iPn0Z76k2keOnoGYt7zhx1T7JS9+KcTUJvdC35XGlSO2e4YqVOTazhCf26idjrEeoqUy5vqntmkNyuwCGm/VxnWxrGwOzc5cDGXEtMXw/Uv/bX4lzbD4ZoAQQghJOFwMEEIIIQmHiwFCCCEk4XAxQAghhCScoQWE0cAhzrOKDa61UJw3sCQnrQCFb9NlLZjrDboQs2aZ/hhHGaooj4q5FUssFTqUUmnLYCSyXT1EJLRlOw5BZTqD4sDAOt9uiJ9LlbRxy3VP2g0xdx7SoqeMw4Cm1bNFhg6xSQeNPfpr+rj9LpoOtTt11c7mcdu7Jyf1MY7gMW4Gw4huXDH2TAkdIrvQMlbyHIZRUaTHM+2okRg5hK3za7pq4MKZExDzpLqu/PakXXsg5nPzWpiV99GYp1KuQF/fMrpabaxCTDqtr3E2jfO71dBzrjKK5mBZ6xmQz6OItr2KwsdO0xItO65RZD07jpxEAeFvvP8PVfvC3BzE/OdfeSpu/Arjea6/12yTmSsnINwwlhjO9/HZPGE9L6a3YzXN/Qd05VDPIbJzGipZbJUqlA/nio7/BuCbAUIIISThcDFACCGEJBwuBgghhJCEw8UAIYQQknCGFhCGAQqj+h1LHNh2uIZltTit53BIyxa1WCjXR5GhsXRCLrHeU74fBT5zi1o8FUXHIabd1uKtbhfFXP2eViYZh8iw3kUHxqJV7bFvUFQ3fbV24tp7HVaHu/NBfdz5Il66clULEXMlrBSWm0Bx4kMPaBe7qI8uX+mKFpgVJyYhZnqPPrd8Zji3sM1gI6IrhwZKVhZ01bylpUWIWbWEb/40Cgjnl89D38lvfk21n97Ez+3drq/nX7uqYg703J0YqUFIz1Hh0nZE8z0cgKZ1bllH5U7P+psjGOAzIFPUcyeTxbnjOcqZFkr6c60OPjtswV3Qwf2fPakFgx/5y7+CmP/8K7/n2PaVxTVPNyKGc33mSorqjDXmLufT2riupumq5tmyqmmOjI5CjF31VQTHzXmml+n87X093sLAy3Ud+WaAEEIISThcDBBCCCEJh4sBQgghJOEMrRlwJV36luFKFGBeqGDl9kODOc2ulQs0GcxNepHOBU6O1SBmfBqNU8b26Lh9+9GUpd7Qxi2B4zz6PZ1nNA6jC6+DmoHuA6dV2++hHqEwU1btNcdg9y3jlHQR13E79us8frGK2oOguBf6Rht63OrzqGsY262r6uUncIxMetbqceSvNwHfca1A8uHM8+m+lI8569NntJbjwhKaOl1Y1H2t1n0Qc/4Cagaqy/pzHauKoYjInRM6h3r46DGICawKcn3HeTTbjgqTnp5zYxNoFrTWsvQQuBWZmp5Q7e07dkLMgQMHVbtYLEBM2ZFTzlg6hiMn8PzvvOdbqj1/bgFicnk958+dx5jNYIv50jhxZaztvtBRCjaX19d4bGICYvoDfF5uBOcwDqUb0m3XuW70El2uXP/l0ijwzQAhhBCScLgYIIQQQhIOFwOEEEJIwuFigBBCCEk4QwsIs2k0+el1GqodOYyJcp7eRRBhjNS0kCR0VM3LZrVIYufuKYhJo+ZIulktdCtuw6DUqI5JZ3BY0iktVPIcVRNbF1A8dtiqNug5qv3ZpkP9AW67WNHiqdo4VnVL57TIstXHcTSOyo4mV7DaKMSMcjXdTtUhJrSq83n+1qha6Frx2oImp3zQEuY4PIdktakFdKsOId5iU8+LB4+dgphmvQF9o1NaUNV1XM/CWb0tRzFNSVniOJfBkKTwg92OPpdKBasdijWOKUHB14+97sdU+zWvejXETFnisbTjeeOq4Ges50mrjZUV//LTt6v2Rz72MYh56NBR1a5U0LCLPAaGEehafTt3obDULvLqktz5G6zaOAyeJaJ1VUjcuBDQ3talt3MlDY34ZoAQQghJOFwMEEIIIQmHiwFCCCEk4QytGXDpAZqrOj/X72GRkLRlIJQuYC5wbO+Mas830bynYBUyyVcx9x+mMecSWolez2F+0evrPGfHoVlIpXWuJu3Isa4urEDfUlMb72y7ZhpiCmVdlKU/34WYfXv0GFXHsZBL1jp/33F5Oz1HvtgqHuU7CsL4vt523lG1Jx9pXUMx4xBxbBHS1jrY8zDXnbHNeQIcz4eOaZObCwtzEGPnRkfHsNhKbw21Br22nofHjqGhjj0vn/F9z4GYQVfPp/Pnz2FMhPeub83xoI8mUpGlP7jx2oMQ8/rX3qraVx+4BmLCvj5GV2rUCM7LyOjnSclhTPSmH/tp1X7OM74PYv7hH76o2mn/yhXxeWwMcxxD5Jo3bI1zadzXyi7ec+nt5Av4vDCWNsuVnh8mjz5MXt9zjKNv9xmH5go+59DFORRHkTVGRhzPZmvOu891CGHFEPDNACGEEJJwuBgghBBCEg4XA4QQQkjC4WKAEEIISThDCwhd4sCBVVHKcwgXIquy4eheFE8VJ7SZSZRyGDv4et3SdYgt1noovIss4UbWQ+FdOaMNRiKHMVIY6fPIQNk7Ea+NAqd+qAVO2Uk8/25Li8fyDpHKQUtkGaVQcDYILSGgoFizO8BjzFpGMeU8jm3W1+efCx0xPS3eSvko5toMfB+P1fN0n++YvClLQHdh1q7KKHL/4UOqvdZC8Wl9VRsTZVJ4XYap/dbroYAvWNXXLhjgfZoraoOq2fNYIbHZRsOsqlUZ1CUiLuT0ueya2Q4xM9N67gYDPA/fEngNUwlPxGFE5AgqZPX5P+XGJ0PM99z0VNUOBy4x12Yw7Eg8doYx69k4j11A6AyxTtVVgXSYjQ9nDIQxnv17xuCvTNuYSDyXSNthmAUbwmczRLl+ydqb2aBYlG8GCCGEkITDxQAhhBCScLgYIIQQQhLO0JoBU8Y8p8npj/uOrfX7Os84sQ9Nd2y7l3od856BlUYvbMOiKfk8FtixjVMKjjy6l9PHGHUxLxNE+nNehHmZoI99A8s0o1oZg5iRnD6XQhoL/PQDnWddbOMYZSJ9ASJHZZ2VOq7/cpbhTKmKOd1GW/dFNYfBU9fWkKCRz2aQTWMuLrQ1D86EtL7mq000lao3dIEhV2oyl9HbiQLMKQYG+wpZrW/Zv2sPxGTzOub46RMQs7ywqNqdJuoD8gXU0uD0wfmdz+l8/EGHoVChoLUjxnGuZqi/S4bI+zoKiNkfC0OHKYx1TJ7n0nWQYblcaoTLth2HrmAYHQFE+K5n2jB5fYeOwDI1Q/MiETFDzEPPns8u7cGl4ZsBQgghJOFwMUAIIYQkHC4GCCGEkITDxQAhhBCScIYWELaMw+TGEkr4DjOVXEULJyrTKPJbWNHCrPll3NfUdm0MlKrgoXcdpiy2SCRKOWRRgRbQeY7KfimxxZIouGr3UZjUsQyMso7P2XqqboDiwN5Aj4lxVE3MWEK10CGc6zuq0+Xyeoy27ShDzNxRPbahS4iZ0cdkGzVtFr5DsBbZxcgcUiXfqsx47vwZiKmU9bzM5VD8GfT1/kcmJyCmXENB7FpTmxU965nPhJjnPee5qv1HH/yfEDN75qw+xnIJYoqlPPQVirqKnMt4LGtVJb3xhqdCTMq65/oOAaVYRmOeS9zlMPqyo0Kn4kx3plKOe9CaEJGjuin5bsdVkdAue4sCQpipBueXS9RnwJzIIRY01n3pvC307wbbUG1Y+GaAEEIISThcDBBCCCEJh4sBQgghJOEMrRmwc9YiDuMWx+aKFZ0HKY9hTvXIUV0AZqWDuebtZW1c0hOMaTnMVHwrX9n2MS9UsNyS/ADzO56Vd845tAeSwvPPWcZMrho1tqFQt+cwRUlbxkgOY4u+lee08+IiIl7KkbvK6HNba+HY2j4tnQ7mjzt5HZROO8ZoE4C8n4gYsU1mHIWnrK5zZ09DTD/U45DJYL6waKXo81mcJ50uXvOdM1Oq/b1PfRrElEpas7C2tgYxKWt/0QDzno4aX+JZxcHGRlDv89offpVq3/QUPMYBFDhyGcDoPpeGYzgHGpz0w+gKjHU/mStaxGd4himv45q7EHOZ7HuG2ZfIIxjobDls4ZCjCJGV//fSeJ9GdpGtyKGnAmMgEYn0/eU7fn8ah7kdBunPeRsce74ZIIQQQhIOFwOEEEJIwuFigBBCCEk4XAwQQgghCWdoAWHgMDIwvi3AQHHa6KhlFuTyVbBEfT2H8i1IayFF6BDCCQgaURjU9/BzBcsIyAxw/1Go+5y2Do6yjaWKVo9FHgrvLE8aCTK4RgtFfy5wiMDsgm2+43h8hyDFFr0FDgFjzxKmRYFjHWkdgGMYNwWnGA36MCa0+ioVNGOq15dUexDh2HmWMc/ZuQsQYxtGiYjsmNEVPqsOY6Lf+8P3q/ad374bYmzzoKzDGKlQRNOhiRG9vze98U0Q84pX/Yhqp7MOQx8wfdqYmG2Y6WSbB8Wfu3RVOfQz2hoCwmEYVtQHDDGgG922/akt8ii4BA7jMahmuYox1hiZyCFE9FGhaz+vTeSoiJhq6RinGVfaihn617o+ng19ihBCCCHfNXAxQAghhCQcLgYIIYSQhMPFACGEEJJwhlYadByV9EKjBQ+ZDIobpidHdQe4kYmUS1qYVR4pQkyxbImeHDqKYtpRMc5a7gSO6lEDqxpbKnBs3HKL6rY7ENJqo3Of7RQ4CPFz4UArSXoO574w1A6QGeNw97PEJYMO7qvTOA99fkHHeQ4R1kRZH+No0SHWtD4XuI5xi4CVxhwxnj7+A/sPQEzZEt5dWEYXzHJeC/hqu3ZDzFobnQP71r3y13/zaYi5466vqHbgOhFL4JTJolixUkTh3w+99MWq/ZrXvA5icnl9/sEA55x4+t7ZoJHgUAwneLv0xj2Pfyd9J9jXwXVdbDGcUxx3mXBv2j4mfKZlM3o+l2t4fweWY23Yw7nj+Y77ItS/fjMOB1s/u2z14ImEfS3Sb7WwKukwcMYTQgghCYeLAUIIISThcDFACCGEJJzh3Qk8Rx470jmWVBrzGcWCzkWmXZUNC7pvpIK5/15Pmy9EwQjEhH1XtT+93gGjJBHpdnU+J+Moa5by9DH2+qgPaDryvvbpdhzVH7OhzuF2HJqFyNIMpAVNYkKrOp9ncF8SLGFXTx93IYvmOuMVrePIOpaR3ZbWXvhpzENvHax54chkR6HOBU5P7YKY66++RrUXlhxVAy2nrdVmA2JanRb0rTTqqn3P6rcgZnp6m2oX1jCn2etow5OMw7Dr+c96DvS97nU/qdq2PkBExIRaN5RyVPMcJo9v601cKV4PnYEkihzmY/bnrGsbOSvB2TnurfF3krMCHZgmDaGBGLrzMgE6EdfOLn3Nh2MYDYhLFGQHoWYgndHP0GIR50W/r+dgN0CDoUzOobGyBG3pFJoO5cr6d5rrVuq39ee6XYd50RBsjRlPCCGEkE2DiwFCCCEk4XAxQAghhCQcLgYIIYSQhDO0gDAVOEIDLRYaq41CSHpUGyDU+yhwEqvS2dgMmibkslq81A0cdQMdfVlLjOc7TIf6RgvfugHG+JaAcK2NIpGz7Xnoq9W0GK/vEICkrcpYoUOcaGnZoIpjfIw6yHcIUrZPo8CrE+ixdZlfZK2KWj1Hhcq0r4Wf3saKZ112PN9xPe0Yx3WJLFOtbdv3Qsz3PPlpqn30+EmIWbMERqdn0fip13MYRJ0+pdo3Xn0txDz7Gd+r2o3VRYi5MKvn5ffc9BSI+bEffTP07d5zULWDPs55ENo5hFqplFXVzeXpZd2XLrGg8yJZXEnjms3Armwngro33yWOu2wMs208SPuQPMeJGOsae0Ndu42d63ACSochndW1UsffTbaINXDo9/oRGn15Rt87vo8C+E5oGfC55kNoVZ3doDCUbwYIIYSQhMPFACGEEJJwuBgghBBCEs7QWd1eD/PxGcvQ59pr9kJMfkTno8+tzeG2rUI9e6/CQi5X7dmv2g/MHYaYgaPAzsAyRRFHrtvPWrkrZ6Egve20o9jLzt3j0FerVlW7kEPjFhnoYyz4aNZTrGrtQa+FugKxjVtCzEG5NBN5SyMQOfJyKSuflckVICaX1vm0YAhDmMcD31UkxdJXuDxmjKXliDw0w/q+Z96i2g8cPgQxn/2KLiY0MTkBMZHDqCTt20Y4OJ7P/l6tGdi99yDERGFoxVwDMRWH3ie0dCK+a4wc9xzs3z7sS3v+iCs3vFE5gP0533Ui8Jmtoj1wmeUMYdB0ZQ7GiXP/tmjANZ523+M+5paWxfGcGPTzVttlAmU3cTsOOzwRSzPhO7RNRvTvGdcQeVaM3R4WvhkghBBCEg4XA4QQQkjC4WKAEEIISThcDBBCCCEJZ2gB4cAhvCtWtFBhexWr3TXbK6rd7vchZq2tK0Ntm0QhXnlEC9ZyF1wSGVzbRBmrkp9LBBXqY4oClHt4kf5gMYciv8IMHnfaEuflUijuCKwhyeXwIIOuDnL5jGR9ve20j5c3SDmEWZagKnQIYPyUVWHLYSJid3mu0oabguuiW+KhCGNsEVTocBPZsfuAar/wRS+HmC/+8x2q7SjuKaPj26DPHvNaEUWb11//VNXed9X1uHFrf3Y1RhER4xB72nqqyPEMMGAWhOMIOjGHiNXVh0GuqoWXNjSyxYCuCnYY83hK8B4ZV/VE+/g3+1jdelCrauEQ5+FUqD6uoHDc9/Rz3iUstbtc18PZZz+XHNv2Pet3qtNgyvodR9MhQgghhGwELgYIIYSQhMPFACGEEJJwhtcMBA6Tm7TOrdc7WKin0dN6gJ7BfHwqo9ckq/06xDxw4gHV7ju0B4Ejp+lldB59EDn2byVV+w7NQDqtDWdSDmMiP4PJmpSdwHHkhTIZS1eQwcvSH7TsA8Jj9C+tT0i5cl7WIfoZxxrREgREAW6n19bHmMpszPzicuPMqUKXK8+n274j72nXxrrhSTdDzL/+ydtU+7577oKY8VHUm6ysNlT7Oc95AcRMb9+j2oOBw97ETs0OZfrj6sQ5D5PHmbCE0joYYRetGUZD4NqTY37jLbhVDIUujW18FfdZmoFhLIaceewNH5Z1QA5TL9HH7TLMsg2roit6XVxikiE+ZR33MIfoNAZyDDY8T1zjOMT+PM+eIxu7d/hmgBBCCEk4XAwQQgghCYeLAUIIISThcDFACCGEJBzPPJHUNIQQQgi57PDNACGEEJJwuBgghBBCEg4XA4QQQkjC4WKAEEIISThcDBBCCCEJh4sBQgghJOFwMUAIIYQkHC4GCCGEkITDxQAhhBCScP5/rDbQN6kS+YUAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 640x480 with 6 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "\n",
    "def visualize_model(best_ckpt_path, dataset_val):\n",
    "    num_class = 10\n",
    "    net = resnet50(num_class)\n",
    "    # 加载模型参数\n",
    "    param_dict = ms.load_checkpoint(best_ckpt_path)\n",
    "    ms.load_param_into_net(net, param_dict)\n",
    "    # 加载验证集的数据进行验证\n",
    "    data = next(dataset_val.create_dict_iterator())\n",
    "    images = data[\"image\"]\n",
    "    labels = data[\"label\"]\n",
    "    # 预测图像类别\n",
    "    output = net(data['image'])\n",
    "    pred = np.argmax(output.asnumpy(), axis=1)\n",
    "\n",
    "    # 图像分类\n",
    "    classes = []\n",
    "\n",
    "    with open(data_dir + \"/batches.meta.txt\", \"r\") as f:\n",
    "        for line in f:\n",
    "            line = line.rstrip()\n",
    "            if line:\n",
    "                classes.append(line)\n",
    "\n",
    "    # 显示图像及图像的预测值\n",
    "    plt.figure()\n",
    "    for i in range(6):\n",
    "        plt.subplot(2, 3, i + 1)\n",
    "        # 若预测正确，显示为蓝色；若预测错误，显示为红色\n",
    "        color = 'blue' if pred[i] == labels.asnumpy()[i] else 'red'\n",
    "        plt.title('predict:{}'.format(classes[pred[i]]), color=color)\n",
    "        picture_show = np.transpose(images.asnumpy()[i], (1, 2, 0))\n",
    "        mean = np.array([0.4914, 0.4822, 0.4465])\n",
    "        std = np.array([0.2023, 0.1994, 0.2010])\n",
    "        picture_show = std * picture_show + mean\n",
    "        picture_show = np.clip(picture_show, 0, 1)\n",
    "        plt.imshow(picture_show)\n",
    "        plt.axis('off')\n",
    "\n",
    "    plt.show()\n",
    "\n",
    "\n",
    "# 使用测试数据集进行验证\n",
    "visualize_model(best_ckpt_path=best_ckpt_path, dataset_val=dataset_val)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7a2a6920-995c-4c92-af54-7a470c472df1",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.21"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
